@h-ai/deploy 1.0.0-beta.3 → 1.0.0-beta.5
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 +9 -3
- package/README.ja.md +9 -3
- package/README.md +9 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +80 -13
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/deploy-artifact.ts","../messages/en-US.json","../messages/ja-JP.json","../messages/zh-CN.json","../src/deploy-i18n.ts","../src/deploy-config.ts","../src/deploy-types.ts","../src/deploy-environment.ts","../src/deploy-functions.ts","../src/deploy-credentials.ts","../src/deploy-middleware-config.ts","../src/deploy-recovery.ts","../src/deploy-scanner.ts","../src/container/deploy-compose-identity.ts","../src/container/deploy-managed-secrets.ts","../src/container/deploy-backend-state.ts","../src/container/deploy-command-windows.ts","../src/container/deploy-command-process.ts","../src/container/deploy-secret-masker.ts","../src/container/deploy-command.ts","../src/container/deploy-ssh-askpass.ts","../src/container/deploy-target.ts","../src/container/deploy-scripts.ts","../src/container/deploy-ssh.ts","../src/container/deploy-bundle.ts","../src/container/deploy-https.ts","../src/container/deploy-container-compose.ts","../src/providers/deploy-provider-docker-ssh.ts","../src/providers/deploy-provider-vercel.ts","../src/provisioners/deploy-provisioner-aliyun.ts","../src/provisioners/deploy-provisioner-neon.ts","../src/provisioners/deploy-provisioner-r2.ts","../src/provisioners/deploy-provisioner-resend.ts","../src/provisioners/deploy-provisioner-upstash.ts","../src/deploy-main.ts","../src/deploy-middleware.ts","../src/deploy-plan.ts","../src/deploy-secrets.ts"],"names":["z","core","field","existsSync","readFileSync","resolve","process","privateFile","join","dirname","parse","writeFileSync","ok","err","logger","parseEnv","key","setTimeout","lstatSync","chmodSync","helper","basename","mkdtempSync","mkdirSync","createHash","rmSync","createReadStream","stringify","randomBytes","request","requestHttps","deploy","name","prepared","resolveTransportBodyLimits","relative","statSync","connectionUri","Buffer","readdirSync","groups","realpathSync","randomUUID","spawn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoBO,IAAM,wBAAA,GAA2B,EAAE,MAAA,CAAO;AAAA;AAAA,EAE/C,OAAA,EAAS,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAC,CAAA;AAAA;AAAA,EAE7C,gBAAgB,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,EAAQ,KAAK,CAAC,CAAA;AAAA;AAAA,EAEtC,UAAA,EAAY,EAAE,MAAA,EAAO,CAAE,IAAI,EAAE,CAAA,CAAE,MAAM,sHAAsH,CAAA;AAAA;AAAA,EAE3J,OAAA,EAAS,EAAE,MAAA,EAAO,CAAE,IAAI,GAAG,CAAA,CAAE,MAAM,qBAAqB,CAAA;AAAA;AAAA,EAExD,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA;AAAA,EAElC,MAAA,EAAQ,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA;AAAA,EAEjC,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,WAAS,KAAA,KAAU,EAAA,IAAO,2BAAA,CAA4B,IAAA,CAAK,KAAK,CAAA,IAAK,CAAC,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,IAAA,CAAK,CAAA,OAAA,KAAW,OAAA,KAAY,GAAA,IAAO,OAAA,KAAY,IAAI,CAAE,CAAA,CAAE,QAAA,EAAS;AAAA;AAAA,EAEtL,iBAAA,EAAmB,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA,CAAE,QAAA,EAAS;AAAA;AAAA,EAE/D,gBAAA,EAAkB,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA,CAAE,QAAA,EAAS;AAAA;AAAA,EAE9D,MAAA,EAAQ,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,MAAA,CAAO;AAAA;AAAA,IAEvB,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,EAAQ,KAAK,CAAC,CAAA;AAAA;AAAA,IAE5B,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,MAAM,iBAAiB,CAAA;AAAA;AAAA,IAExC,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,KAAA,CAAM,gDAAgD,CAAA,CAAE,MAAA,CAAO,CAAA,KAAA,KAAS,CAAC,KAAA,CAAM,QAAA,CAAS,SAAS,CAAC,CAAA;AAAA;AAAA,IAEvH,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,CAAE,MAAM,gBAAgB,CAAA;AAAA;AAAA,IAEzC,aAAA,EAAe,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA,CAAE,QAAA;AAAS,GAC5D,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,MAAA,CAAO,CAAA,MAAA,KAAU,IAAI,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,KAAA,KAAS,KAAA,CAAM,IAAI,CAAC,CAAA,CAAE,IAAA,KAAS,MAAA,CAAO,MAAM;AACpG,CAAC,CAAA,CAAE,OAAO,CAAA,QAAA,KAAY,QAAA,CAAS,YAAY,CAAA,GAAI,CAAC,CAAC,QAAA,CAAS,WAAA,GAAc,CAAC,QAAA,CAAS,WAAW,EAAE,MAAA,CAAO,CAAA,QAAA,KAAY,CAAC,QAAA,CAAS,WAAA,IAAe,SAAS,MAAM,CAAA,CAAE,OAAO,CAAA,QAAA,KAAY,QAAA,CAAS,OAAO,KAAA,CAAM,CAAA,KAAA,KAAS,MAAM,IAAA,KAAS,CAAA,EAAG,MAAM,IAAI,CAAA,CAAA,EAAI,SAAS,UAAU,CAAA,IAAA,CAAM,CAAC,CAAA,CAAE,MAAA,CAAO,cAAY,QAAA,CAAS,cAAA,KAAmB,SAAS,QAAA,CAAS,MAAM,EAAE,MAAA,CAAO,CAAA,QAAA,KAAY,SAAS,MAAA,CAAO,KAAA,CAAM,WAAS,KAAA,CAAM,IAAA,KAAS,SAAS,cAAA,IAAmB,KAAA,CAAM,SAAS,KAAA,IAAS,QAAA,CAAS,MAAO,CAAC,CAAA,CAAE,OAAO,CAAA,QAAA,KAAY,QAAA,CAAS,WAAW,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA,KAAA,KAAS,KAAA,CAAM,SAAS,QAAA,CAAS,cAAc,CAAC,CAAA,CAAE,MAAA,CAAO,cAAY,QAAA,CAAS,OAAA,IAAW,CAAC,QAAA,CAAS,MAAA,IAAU,SAAS,MAAA,CAAO,IAAA,CAAK,WAAS,KAAA,CAAM,IAAA,KAAS,KAAK,CAAC;AA2BvrB,eAAsB,iBAAiB,IAAA,EAA+B;AACpE,EAAA,MAAM,IAAA,GAAO,WAAW,QAAQ,CAAA;AAChC,EAAA,WAAA,MAAiB,KAAA,IAAS,iBAAiB,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,OAAO,KAAK,CAAA;AACnB,EAAA,OAAO,IAAA,CAAK,OAAO,KAAK,CAAA;AAC1B;AAeA,eAAsB,uBAAuB,SAAA,EAAgD;AAC3F,EAAA,MAAM,QAAA,GAAW,wBAAA,CAAyB,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,OAAA,CAAQ,SAAA,EAAW,eAAe,CAAA,EAAG,MAAM,CAAC,CAAC,CAAA;AACrH,EAAA,KAAA,MAAW,KAAA,IAAS,SAAS,MAAA,EAAQ;AACnC,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,SAAA,EAAW,KAAA,CAAM,IAAI,CAAA;AAC1C,IAAA,IAAI,CAAC,UAAA,CAAW,IAAI,KAAK,CAAC,SAAA,CAAU,IAAI,CAAA,CAAE,MAAA,MAAY,SAAA,CAAU,IAAI,EAAE,cAAA,EAAe,IAAK,MAAM,gBAAA,CAAiB,IAAI,MAAM,KAAA,CAAM,MAAA;AAC/H,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,KAAA,CAAM,IAAI,CAAA,CAAE,CAAA;AAAA,EACrD;AACA,EAAA,OAAO,QAAA;AACT;;;AC3GA,IAAA,aAAA,GAAA;AAAA,EACE,qBAAA,EAAyB,yDAAA;AAAA,EACzB,iBAAA,EAAqB,8CAAA;AAAA,EACrB,8BAAA,EAAkC,0CAAA;AAAA,EAClC,iCAAA,EAAqC,8CAAA;AAAA,EACrC,0BAAA,EAA8B,mCAAA;AAAA,EAC9B,mBAAA,EAAuB,yBAAA;AAAA,EACvB,iBAAA,EAAqB,gCAAA;AAAA,EACrB,0BAAA,EAA8B,kCAAA;AAAA,EAC9B,mBAAA,EAAuB,qCAAA;AAAA,EACvB,mBAAA,EAAuB,4BAAA;AAAA,EACvB,sBAAA,EAA0B,kDAAA;AAAA,EAC1B,qBAAA,EAAyB,6DAAA;AAAA,EACzB,iBAAA,EAAqB,kCAAA;AAAA,EACrB,mBAAA,EAAuB,4CAAA;AAAA,EACvB,sBAAA,EAA0B,uCAAA;AAAA,EAC1B,2BAAA,EAA+B,uEAAA;AAAA,EAC/B,sBAAA,EAA0B,mBAAA;AAAA,EAC1B,uBAAA,EAA2B,oBAAA;AAAA,EAC3B,kBAAA,EAAsB,8BAAA;AAAA,EACtB,wBAAA,EAA4B,qCAAA;AAAA,EAC5B,eAAA,EAAmB,gCAAA;AAAA,EACnB,uBAAA,EAA2B,+BAAA;AAAA,EAC3B,wBAAA,EAA4B,4CAAA;AAAA,EAC5B,sBAAA,EAA0B,8DAAA;AAAA,EAC1B,yBAAA,EAA6B,8QAAA;AAAA,EAC7B,qBAAA,EAAyB,8BAAA;AAAA,EACzB,oBAAA,EAAwB,qCAAA;AAAA,EACxB,0BAAA,EAA8B,+CAAA;AAAA,EAC9B,2BAAA,EAA+B,6DAAA;AAAA,EAC/B,0BAAA,EAA8B,gCAAA;AAAA,EAC9B,wBAAA,EAA4B,6CAAA;AAAA,EAC5B,yBAAA,EAA6B,+FAAA;AAAA,EAC7B,yBAAA,EAA6B,6EAAA;AAAA,EAC7B,4BAAA,EAAgC,yEAAA;AAAA,EAChC,6BAAA,EAAiC,0EAAA;AAAA,EACjC,2BAAA,EAA+B,qEAAA;AAAA,EAC/B,oBAAA,EAAwB,iDAAA;AAAA,EACxB,sBAAA,EAA0B,+CAAA;AAAA,EAC1B,oBAAA,EAAwB,mEAAA;AAAA,EACxB,mBAAA,EAAuB,gDAAA;AAAA,EACvB,mBAAA,EAAuB,8CAAA;AAAA,EACvB,qBAAA,EAAyB,iDAAA;AAAA,EACzB,oBAAA,EAAwB,uCAAA;AAAA,EACxB,sBAAA,EAA0B,yDAAA;AAAA,EAC1B,kBAAA,EAAsB,+EAAA;AAAA,EACtB,qBAAA,EAAyB,kDAAA;AAAA,EACzB,mBAAA,EAAuB,6EAAA;AAAA,EACvB,iBAAA,EAAqB,0EAAA;AAAA,EACrB,sBAAA,EAA0B,6GAAA;AAAA,EAC1B,sBAAA,EAA0B,uGAAA;AAAA,EAC1B,0BAAA,EAA8B,mIAAA;AAAA,EAC9B,mCAAA,EAAuC,+JAAA;AAAA,EACvC,6BAAA,EAAiC,wJAAA;AAAA,EACjC,sBAAA,EAA0B,qIAAA;AAAA,EAC1B,kBAAA,EAAsB,mHAAA;AAAA,EACtB,yBAAA,EAA6B,wFAAA;AAAA,EAC7B,uBAAA,EAA2B,4FAAA;AAAA,EAC3B,8BAAA,EAAkC,+FAAA;AAAA,EAClC,iBAAA,EAAqB,0HAAA;AAAA,EACrB,wBAAA,EAA4B,wMAAA;AAAA,EAC5B,yBAAA,EAA6B,wnCAAA;AAAA,EAC7B,qBAAA,EAAyB,6GAAA;AAAA,EACzB,iBAAA,EAAqB,uGAAA;AAAA,EACrB,iBAAA,EAAqB,wCAAA;AAAA,EACrB,qBAAA,EAAyB,2GAAA;AAAA,EACzB,yBAAA,EAA6B,yKAAA;AAAA,EAC7B,2BAAA,EAA+B,sKAAA;AAAA,EAC/B,kCAAA,EAAsC,uGAAA;AAAA,EACtC,kCAAA,EAAsC,sEAAA;AAAA,EACtC,sBAAA,EAA0B,0KAAA;AAAA,EAC1B,mBAAA,EAAuB,qIAAA;AAAA,EACvB,0BAAA,EAA8B,4DAAA;AAAA,EAC9B,4BAAA,EAAgC,wEAAA;AAAA,EAChC,uBAAA,EAA2B,4EAAA;AAAA,EAC3B,2BAAA,EAA+B,0DAAA;AAAA,EAC/B,4BAAA,EAAgC,sHAAA;AAAA,EAChC,mBAAA,EAAuB,oDAAA;AAAA,EACvB,wBAAA,EAA4B,4EAAA;AAAA,EAC5B,2BAAA,EAA+B,wEAAA;AAAA,EAC/B,wBAAA,EAA4B,kIAAA;AAAA,EAC5B,mBAAA,EAAuB,2DAAA;AAAA,EACvB,mBAAA,EAAuB,+EAAA;AAAA,EACvB,sBAAA,EAA0B,oCAAA;AAAA,EAC1B,0BAAA,EAA8B,mCAAA;AAAA,EAC9B,yBAAA,EAA6B,sBAAA;AAAA,EAC7B,wBAAA,EAA4B,6DAAA;AAAA,EAC5B,6BAAA,EAAiC,0BAAA;AAAA,EACjC,oBAAA,EAAwB,+IAAA;AAAA,EACxB,qBAAA,EAAyB,0IAAA;AAAA,EACzB,4BAAA,EAAgC,wGAAA;AAAA,EAChC,iBAAA,EAAqB,iBAAA;AAAA,EACrB,oBAAA,EAAwB,0DAAA;AAAA,EACxB,sBAAA,EAA0B,4GAAA;AAAA,EAC1B,gCAAA,EAAoC,iFAAA;AAAA,EACpC,8BAAA,EAAkC,gPAAA;AAAA,EAClC,2BAAA,EAA+B,6BAAA;AAAA,EAC/B,gCAAA,EAAoC,+HAAA;AAAA,EACpC,8BAAA,EAAkC,0DAAA;AAAA,EAClC,4BAAA,EAAgC,yEAAA;AAAA,EAChC,4BAAA,EAAgC,0IAAA;AAAA,EAChC,yBAAA,EAA6B,+OAAA;AAAA,EAC7B,0BAAA,EAA8B,+GAAA;AAAA,EAC9B,iCAAA,EAAqC,sGAAA;AAAA,EACrC,2BAAA,EAA+B,+MAAA;AAAA,EAC/B,wBAAA,EAA4B,qFAAA;AAAA,EAC5B,8BAAA,EAAkC;AACpC,CAAA;;;AC3GA,IAAA,aAAA,GAAA;AAAA,EACE,qBAAA,EAAyB,qNAAA;AAAA,EACzB,iBAAA,EAAqB,mIAAA;AAAA,EACrB,8BAAA,EAAkC,4HAAA;AAAA,EAClC,iCAAA,EAAqC,kIAAA;AAAA,EACrC,0BAAA,EAA8B,0HAAA;AAAA,EAC9B,mBAAA,EAAuB,4CAAA;AAAA,EACvB,iBAAA,EAAqB,iEAAA;AAAA,EACrB,0BAAA,EAA8B,2GAAA;AAAA,EAC9B,mBAAA,EAAuB,mIAAA;AAAA,EACvB,mBAAA,EAAuB,6EAAA;AAAA,EACvB,sBAAA,EAA0B,2GAAA;AAAA,EAC1B,qBAAA,EAAyB,+OAAA;AAAA,EACzB,iBAAA,EAAqB,mIAAA;AAAA,EACrB,mBAAA,EAAuB,+FAAA;AAAA,EACvB,sBAAA,EAA0B,2GAAA;AAAA,EAC1B,2BAAA,EAA+B,+JAAA;AAAA,EAC/B,sBAAA,EAA0B,oEAAA;AAAA,EAC1B,uBAAA,EAA2B,0EAAA;AAAA,EAC3B,kBAAA,EAAsB,iEAAA;AAAA,EACtB,wBAAA,EAA4B,sGAAA;AAAA,EAC5B,eAAA,EAAmB,qDAAA;AAAA,EACnB,uBAAA,EAA2B,kIAAA;AAAA,EAC3B,wBAAA,EAA4B,2GAAA;AAAA,EAC5B,sBAAA,EAA0B,2KAAA;AAAA,EAC1B,yBAAA,EAA6B,syBAAA;AAAA,EAC7B,qBAAA,EAAyB,uGAAA;AAAA,EACzB,oBAAA,EAAwB,kGAAA;AAAA,EACxB,0BAAA,EAA8B,2GAAA;AAAA,EAC9B,2BAAA,EAA+B,sLAAA;AAAA,EAC/B,0BAAA,EAA8B,+FAAA;AAAA,EAC9B,wBAAA,EAA4B,iMAAA;AAAA,EAC5B,yBAAA,EAA6B,qQAAA;AAAA,EAC7B,yBAAA,EAA6B,0MAAA;AAAA,EAC7B,4BAAA,EAAgC,0NAAA;AAAA,EAChC,6BAAA,EAAiC,oNAAA;AAAA,EACjC,2BAAA,EAA+B,gRAAA;AAAA,EAC/B,oBAAA,EAAwB,0KAAA;AAAA,EACxB,sBAAA,EAA0B,kJAAA;AAAA,EAC1B,oBAAA,EAAwB,kPAAA;AAAA,EACxB,mBAAA,EAAuB,kJAAA;AAAA,EACvB,mBAAA,EAAuB,oHAAA;AAAA,EACvB,qBAAA,EAAyB,0JAAA;AAAA,EACzB,oBAAA,EAAwB,8GAAA;AAAA,EACxB,sBAAA,EAA0B,wKAAA;AAAA,EAC1B,kBAAA,EAAsB,0NAAA;AAAA,EACtB,qBAAA,EAAyB,oKAAA;AAAA,EACzB,mBAAA,EAAuB,+LAAA;AAAA,EACvB,iBAAA,EAAqB,qJAAA;AAAA,EACrB,sBAAA,EAA0B,iTAAA;AAAA,EAC1B,sBAAA,EAA0B,iRAAA;AAAA,EAC1B,0BAAA,EAA8B,4WAAA;AAAA,EAC9B,mCAAA,EAAuC,4cAAA;AAAA,EACvC,6BAAA,EAAiC,yZAAA;AAAA,EACjC,sBAAA,EAA0B,qXAAA;AAAA,EAC1B,kBAAA,EAAsB,oUAAA;AAAA,EACtB,yBAAA,EAA6B,yOAAA;AAAA,EAC7B,uBAAA,EAA2B,0NAAA;AAAA,EAC3B,8BAAA,EAAkC,yRAAA;AAAA,EAClC,iBAAA,EAAqB,6OAAA;AAAA,EACrB,wBAAA,EAA4B,oXAAA;AAAA,EAC5B,yBAAA,EAA6B,+1FAAA;AAAA,EAC7B,qBAAA,EAAyB,6LAAA;AAAA,EACzB,iBAAA,EAAqB,sUAAA;AAAA,EACrB,iBAAA,EAAqB,8GAAA;AAAA,EACrB,qBAAA,EAAyB,wVAAA;AAAA,EACzB,yBAAA,EAA6B,ocAAA;AAAA,EAC7B,2BAAA,EAA+B,8aAAA;AAAA,EAC/B,kCAAA,EAAsC,0TAAA;AAAA,EACtC,kCAAA,EAAsC,mKAAA;AAAA,EACtC,sBAAA,EAA0B,ucAAA;AAAA,EAC1B,mBAAA,EAAuB,gVAAA;AAAA,EACvB,0BAAA,EAA8B,2IAAA;AAAA,EAC9B,4BAAA,EAAgC,wLAAA;AAAA,EAChC,uBAAA,EAA2B,gPAAA;AAAA,EAC3B,2BAAA,EAA+B,8LAAA;AAAA,EAC/B,4BAAA,EAAgC,+XAAA;AAAA,EAChC,mBAAA,EAAuB,oJAAA;AAAA,EACvB,wBAAA,EAA4B,6NAAA;AAAA,EAC5B,2BAAA,EAA+B,8LAAA;AAAA,EAC/B,wBAAA,EAA4B,4XAAA;AAAA,EAC5B,mBAAA,EAAuB,oKAAA;AAAA,EACvB,mBAAA,EAAuB,kPAAA;AAAA,EACvB,sBAAA,EAA0B,8GAAA;AAAA,EAC1B,0BAAA,EAA8B,sIAAA;AAAA,EAC9B,yBAAA,EAA6B,gFAAA;AAAA,EAC7B,wBAAA,EAA4B,kJAAA;AAAA,EAC5B,6BAAA,EAAiC,sFAAA;AAAA,EACjC,oBAAA,EAAwB,+ZAAA;AAAA,EACxB,qBAAA,EAAyB,2bAAA;AAAA,EACzB,4BAAA,EAAgC,8RAAA;AAAA,EAChC,iBAAA,EAAqB,sCAAA;AAAA,EACrB,oBAAA,EAAwB,gIAAA;AAAA,EACxB,sBAAA,EAA0B,2MAAA;AAAA,EAC1B,gCAAA,EAAoC,0JAAA;AAAA,EACpC,8BAAA,EAAkC,qiBAAA;AAAA,EAClC,2BAAA,EAA+B,oFAAA;AAAA,EAC/B,gCAAA,EAAoC,wSAAA;AAAA,EACpC,8BAAA,EAAkC,oKAAA;AAAA,EAClC,4BAAA,EAAgC,yKAAA;AAAA,EAChC,4BAAA,EAAgC,oWAAA;AAAA,EAChC,yBAAA,EAA6B,+pBAAA;AAAA,EAC7B,0BAAA,EAA8B,ySAAA;AAAA,EAC9B,iCAAA,EAAqC,sQAAA;AAAA,EACrC,2BAAA,EAA+B,0gBAAA;AAAA,EAC/B,wBAAA,EAA4B,6OAAA;AAAA,EAC5B,8BAAA,EAAkC;AACpC,CAAA;;;AC3GA,IAAA,aAAA,GAAA;AAAA,EACE,qBAAA,EAAyB,+FAAA;AAAA,EACzB,iBAAA,EAAqB,gEAAA;AAAA,EACrB,8BAAA,EAAkC,0EAAA;AAAA,EAClC,iCAAA,EAAqC,2EAAA;AAAA,EACrC,0BAAA,EAA8B,yDAAA;AAAA,EAC9B,mBAAA,EAAuB,sCAAA;AAAA,EACvB,iBAAA,EAAqB,uCAAA;AAAA,EACrB,0BAAA,EAA8B,mDAAA;AAAA,EAC9B,mBAAA,EAAuB,+DAAA;AAAA,EACvB,mBAAA,EAAuB,uCAAA;AAAA,EACvB,sBAAA,EAA0B,2EAAA;AAAA,EAC1B,qBAAA,EAAyB,4FAAA;AAAA,EACzB,iBAAA,EAAqB,mDAAA;AAAA,EACrB,mBAAA,EAAuB,+DAAA;AAAA,EACvB,sBAAA,EAA0B,mDAAA;AAAA,EAC1B,2BAAA,EAA+B,kGAAA;AAAA,EAC/B,sBAAA,EAA0B,gCAAA;AAAA,EAC1B,uBAAA,EAA2B,gCAAA;AAAA,EAC3B,kBAAA,EAAsB,mDAAA;AAAA,EACtB,wBAAA,EAA4B,oDAAA;AAAA,EAC5B,eAAA,EAAmB,4DAAA;AAAA,EACnB,uBAAA,EAA2B,0DAAA;AAAA,EAC3B,wBAAA,EAA4B,sDAAA;AAAA,EAC5B,sBAAA,EAA0B,2GAAA;AAAA,EAC1B,yBAAA,EAA6B,gZAAA;AAAA,EAC7B,qBAAA,EAAyB,qDAAA;AAAA,EACzB,oBAAA,EAAwB,wEAAA;AAAA,EACxB,0BAAA,EAA8B,sEAAA;AAAA,EAC9B,2BAAA,EAA+B,iGAAA;AAAA,EAC/B,0BAAA,EAA8B,mDAAA;AAAA,EAC9B,wBAAA,EAA4B,uFAAA;AAAA,EAC5B,yBAAA,EAA6B,kLAAA;AAAA,EAC7B,yBAAA,EAA6B,qKAAA;AAAA,EAC7B,4BAAA,EAAgC,sIAAA;AAAA,EAChC,6BAAA,EAAiC,0HAAA;AAAA,EACjC,2BAAA,EAA+B,0HAAA;AAAA,EAC/B,oBAAA,EAAwB,kGAAA;AAAA,EACxB,sBAAA,EAA0B,kGAAA;AAAA,EAC1B,oBAAA,EAAwB,gIAAA;AAAA,EACxB,mBAAA,EAAuB,gFAAA;AAAA,EACvB,mBAAA,EAAuB,0EAAA;AAAA,EACvB,qBAAA,EAAyB,mFAAA;AAAA,EACzB,oBAAA,EAAwB,8DAAA;AAAA,EACxB,sBAAA,EAA0B,qFAAA;AAAA,EAC1B,kBAAA,EAAsB,0HAAA;AAAA,EACtB,qBAAA,EAAyB,4FAAA;AAAA,EACzB,mBAAA,EAAuB,gIAAA;AAAA,EACvB,iBAAA,EAAqB,sIAAA;AAAA,EACrB,sBAAA,EAA0B,oLAAA;AAAA,EAC1B,sBAAA,EAA0B,wKAAA;AAAA,EAC1B,0BAAA,EAA8B,6QAAA;AAAA,EAC9B,mCAAA,EAAuC,oSAAA;AAAA,EACvC,6BAAA,EAAiC,0QAAA;AAAA,EACjC,sBAAA,EAA0B,iRAAA;AAAA,EAC1B,kBAAA,EAAsB,8LAAA;AAAA,EACtB,yBAAA,EAA6B,8IAAA;AAAA,EAC7B,uBAAA,EAA2B,4IAAA;AAAA,EAC3B,8BAAA,EAAkC,mJAAA;AAAA,EAClC,iBAAA,EAAqB,sLAAA;AAAA,EACrB,wBAAA,EAA4B,mUAAA;AAAA,EAC5B,yBAAA,EAA6B,09DAAA;AAAA,EAC7B,qBAAA,EAAyB,wJAAA;AAAA,EACzB,iBAAA,EAAqB,8MAAA;AAAA,EACrB,iBAAA,EAAqB,6EAAA;AAAA,EACrB,qBAAA,EAAyB,+KAAA;AAAA,EACzB,yBAAA,EAA6B,sRAAA;AAAA,EAC7B,2BAAA,EAA+B,kRAAA;AAAA,EAC/B,kCAAA,EAAsC,yNAAA;AAAA,EACtC,kCAAA,EAAsC,0GAAA;AAAA,EACtC,sBAAA,EAA0B,yPAAA;AAAA,EAC1B,mBAAA,EAAuB,wNAAA;AAAA,EACvB,0BAAA,EAA8B,oEAAA;AAAA,EAC9B,4BAAA,EAAgC,0GAAA;AAAA,EAChC,uBAAA,EAA2B,4JAAA;AAAA,EAC3B,2BAAA,EAA+B,oGAAA;AAAA,EAC/B,4BAAA,EAAgC,8LAAA;AAAA,EAChC,mBAAA,EAAuB,sEAAA;AAAA,EACvB,wBAAA,EAA4B,8KAAA;AAAA,EAC5B,2BAAA,EAA+B,6IAAA;AAAA,EAC/B,wBAAA,EAA4B,4OAAA;AAAA,EAC5B,mBAAA,EAAuB,4FAAA;AAAA,EACvB,mBAAA,EAAuB,oKAAA;AAAA,EACvB,sBAAA,EAA0B,wDAAA;AAAA,EAC1B,0BAAA,EAA8B,wDAAA;AAAA,EAC9B,yBAAA,EAA6B,sCAAA;AAAA,EAC7B,wBAAA,EAA4B,sFAAA;AAAA,EAC5B,6BAAA,EAAiC,sCAAA;AAAA,EACjC,oBAAA,EAAwB,uPAAA;AAAA,EACxB,qBAAA,EAAyB,iQAAA;AAAA,EACzB,4BAAA,EAAgC,oKAAA;AAAA,EAChC,iBAAA,EAAqB,0BAAA;AAAA,EACrB,oBAAA,EAAwB,wGAAA;AAAA,EACxB,sBAAA,EAA0B,yKAAA;AAAA,EAC1B,gCAAA,EAAoC,kIAAA;AAAA,EACpC,8BAAA,EAAkC,gXAAA;AAAA,EAClC,2BAAA,EAA+B,yEAAA;AAAA,EAC/B,gCAAA,EAAoC,8MAAA;AAAA,EACpC,8BAAA,EAAkC,kGAAA;AAAA,EAClC,4BAAA,EAAgC,0HAAA;AAAA,EAChC,4BAAA,EAAgC,wMAAA;AAAA,EAChC,yBAAA,EAA6B,kZAAA;AAAA,EAC7B,0BAAA,EAA8B,iLAAA;AAAA,EAC9B,iCAAA,EAAqC,qKAAA;AAAA,EACrC,2BAAA,EAA+B,mXAAA;AAAA,EAC/B,wBAAA,EAA4B,4KAAA;AAAA,EAC5B,8BAAA,EAAkC;AACpC,CAAA;;;ACvEO,IAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,mBAAA,CAAsC;AAAA,EACrE,OAAA,EAAS,aAAA;AAAA,EACT,OAAA,EAAS,aAAA;AAAA,EACT,OAAA,EAAS;AACX,CAAC,CAAA;;;AC3BD,IAAM,0BAAA,GAA6BA,EAAE,MAAA,CAAO;AAAA,EAC1C,IAAA,EAAMA,CAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,EACxB,KAAA,EAAOA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAA,EAAG,OAAA,CAAQ,4BAA4B,CAAC;AAChE,CAAC,CAAA;AAGD,IAAM,eAAA,GAAkBA,EAAE,MAAA,CAAO;AAAA;AAAA,EAE/B,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,MAAM,yBAAyB,CAAA;AAAA;AAAA,EAEhD,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA,CAAE,QAAQ,EAAE,CAAA;AAAA;AAAA,EAEnD,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,MAAM,iBAAiB,CAAA;AAAA;AAAA,EAE5C,IAAA,EAAMA,EAAE,IAAA,CAAK,CAAC,OAAO,UAAU,CAAC,EAAE,QAAA,EAAS;AAAA;AAAA,EAE3C,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAE9B,cAAcA,CAAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,QAAA,EAAS;AAAA;AAAA,EAEzC,gBAAgBA,CAAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,QAAA,EAAS;AAAA;AAAA,EAE3C,qBAAA,EAAuBA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAE/C,qBAAA,EAAuBA,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,EAAE;AAC/D,CAAC,CAAA,CAAE,WAAA,CAAY,CAAC,GAAA,EAAK,OAAA,KAAY;AAE/B,EAAA,IAAI,IAAI,IAAA,KAAS,KAAA,IAAU,IAAI,IAAA,KAAS,MAAA,IAAa,CAAC,GAAA,CAAI,QAAA;AACxD,IAAA;AACF,EAAA,IAAI,CAAC,GAAA,CAAI,QAAA,IAAY,UAAA,CAAW,KAAK,GAAA,CAAI,QAAQ,CAAA,IAAK,IAAI,aAAY,CAAE,MAAA,CAAO,GAAA,CAAI,QAAQ,EAAE,MAAA,GAAS,IAAA;AACpG,IAAA,OAAA,CAAQ,QAAA,CAAS,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,UAAU,CAAA,EAAG,OAAA,EAAS,OAAA,CAAQ,2BAA2B,CAAA,EAAG,CAAA;AAC1G,CAAC,CAAA;AAGD,IAAM,oBAAoBA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,CAAA,CAAE,KAAA,CAAM,qCAAqC,CAAA,CAAE,OAAO,CAAA,KAAA,KAAS,CAAC,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA;AAChI,IAAM,YAAA,GAAe;AAAA;AAAA,EAEnB,MAAA,EAAQ,iBAAA,CAAkB,QAAA,CAAS,4FAAsB,CAAA;AAAA;AAAA,EAEzD,MAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,CAAE,SAAS,sGAAgC,CAAA;AAAA;AAAA,EAE/F,YAAA,EAAcA,EAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA,CAAE,SAAS,iJAA6C;AAChG,CAAA;AACA,IAAM,iBAAA,GAAoBA,CAAAA,CAAE,kBAAA,CAAmB,MAAA,EAAQ;AAAA,EACrDA,EAAE,MAAA,CAAO;AAAA,IACP,IAAA,EAAMA,CAAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,IACvB,GAAG,YAAA;AAAA;AAAA,IAEH,eAAA,EAAiBA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,gMAAqC,CAAA;AAAA,IACjF,cAAA,EAAgBA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,mKAAiC;AAAA,GAC7E,CAAA;AAAA,EACDA,EAAE,MAAA,CAAO;AAAA,IACP,IAAA,EAAMA,CAAAA,CAAE,OAAA,CAAQ,aAAa,CAAA;AAAA,IAC7B,GAAG,YAAA;AAAA,IACH,MAAA,EAAQ,iBAAA,CAAkB,MAAA,CAAO,CAAA,KAAA,KAAS,MAAM,QAAA,CAAS,GAAG,CAAA,IAAK,CAAC,oBAAoB,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE,SAAS,uIAA6C,CAAA;AAAA,IACzJ,KAAA,EAAOA,CAAAA,CAAE,KAAA,EAAM,CAAE,SAAS,yDAAsB,CAAA;AAAA;AAAA,IAEhD,aAAaA,CAAAA,CAAE,OAAA,CAAQ,IAAI,CAAA,CAAE,SAAS,+GAAoC;AAAA,GAC3E;AACH,CAAC,CAAA;AAGD,IAAM,gBAAA,GAAmBA,EAAE,MAAA,CAAO;AAAA,EAChC,MAAMA,CAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA,CAAE,QAAQ,MAAM,CAAA;AAAA;AAAA,EAEtC,aAAA,EAAeA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA,CAAE,QAAQ,GAAI,CAAA;AAAA;AAAA,EAE9D,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,KAAK,CAAA;AAAA;AAAA,EAE3C,KAAA,EAAO,iBAAA,CAAkB,QAAA,EAAS,CAAE,SAAS,+LAAkE;AACjH,CAAC,CAAA,CAAE,WAAA,CAAY,CAAC,MAAA,EAAQ,OAAA,KAAY;AAClC,EAAA,IAAI,MAAA,CAAO,KAAA,KAAU,MAAA,CAAO,KAAA,CAAM,IAAA,KAAS,MAAA,CAAO,QAAA,IAAa,MAAA,CAAO,KAAA,CAAM,IAAA,KAAS,aAAA,IAAiB,MAAA,CAAO,QAAA,KAAa,EAAA,CAAA;AACxH,IAAA,OAAA,CAAQ,QAAA,CAAS,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,OAAO,CAAA,EAAG,OAAA,EAAS,OAAA,CAAQ,0BAA0B,CAAA,EAAG,CAAA;AACtG,CAAC,CAAA;AAGD,IAAM,YAAA,GAAe,gBAAA;AAGrB,IAAM,6BAAA,GAAgCA,EAAE,MAAA,CAAO;AAAA,EAC7C,IAAA,EAAMA,CAAAA,CAAE,OAAA,CAAQ,YAAY,CAAA;AAAA;AAAA,EAE5B,GAAA,EAAK,gBAAgB,QAAA,EAAS;AAAA;AAAA,EAE9B,MAAA,EAAQA,EAAE,MAAA,CAAO;AAAA;AAAA,IAEf,SAASA,CAAAA,CAAE,MAAA,GAAS,KAAA,CAAM,eAAe,EAAE,MAAA,CAAO,CAAA,KAAA,KAAS,CAAC,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,QAAA,CAAS,IAAI,CAAC,CAAA,CAAE,QAAQ,eAAe,CAAA;AAAA;AAAA,IAEpH,OAAA,EAASA,CAAAA,CAAE,IAAA,CAAK,CAAC,MAAA,EAAQ,UAAU,QAAQ,CAAC,CAAA,CAAE,OAAA,CAAQ,MAAM;AAAA,GAC7D,EAAE,OAAA,CAAQ,EAAE,SAAS,eAAA,EAAiB,OAAA,EAAS,QAAQ,CAAA;AAAA;AAAA,EAExD,MAAA,EAAQ,YAAA;AAAA;AAAA,EAER,kBAAA,EAAoBA,CAAAA,CAAE,KAAA,CAAMA,CAAAA,CAAE,KAAA,CAAM,CAACA,CAAAA,CAAE,IAAA,EAAK,EAAGA,CAAAA,CAAE,IAAA,EAAK,EAAGA,EAAE,MAAA,EAAO,EAAGA,CAAAA,CAAE,MAAA,EAAQ,CAAC,CAAC,CAAA,CAAE,GAAA,CAAI,GAAI,CAAA,CAAE,QAAA;AAC/F,CAAC,CAAA;AAaM,IAAM,oBAAA,GAAuBA,CAAAA,CAAE,kBAAA,CAAmB,MAAA,EAAQ;AAAA,EAC/D,0BAAA;AAAA,EACA;AACF,CAAC;AAqCD,IAAM,iBAAA,GAAoBA,EAAE,MAAA,CAAO;AAAA,EACjC,WAAA,EAAaA,CAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC7B,MAAA,EAAQA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC1B,CAAC,CAAA;AAGD,IAAM,oBAAA,GAAuBA,EAAE,MAAA,CAAO;AAAA,EACpC,WAAA,EAAaA,CAAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,EAChC,KAAA,EAAOA,CAAAA,CAAE,MAAA,EAAO,CAAE,KAAA,EAAM;AAAA,EACxB,MAAA,EAAQA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC1B,CAAC,CAAA;AAGD,IAAM,eAAA,GAAkBA,EAAE,MAAA,CAAO;AAAA,EAC/B,WAAA,EAAaA,CAAAA,CAAE,OAAA,CAAQ,eAAe,CAAA;AAAA,EACtC,WAAA,EAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC7B,eAAA,EAAiBA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACjC,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC3B,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC5B,CAAC,CAAA;AAGD,IAAM,mBAAA,GAAsBA,EAAE,MAAA,CAAO;AAAA,EACnC,WAAA,EAAaA,CAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,EAC/B,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,KAAA,EAAM;AAAA,EACvB,MAAA,EAAQA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC1B,CAAC,CAAA;AAGD,IAAM,sBAAA,GAAyBA,EAAE,MAAA,CAAO;AAAA,EACtC,WAAA,EAAaA,CAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,EAC/B,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC1B,WAAA,EAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC7B,eAAA,EAAiBA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AACnC,CAAC,CAAA;AAGD,IAAM,oBAAA,GAAuBA,EAAE,MAAA,CAAO;AAAA,EACpC,EAAA,EAAIA,EAAE,kBAAA,CAAmB,aAAA,EAAe,CAAC,iBAAiB,CAAC,EAAE,QAAA,EAAS;AAAA,EACtE,KAAA,EAAOA,EAAE,kBAAA,CAAmB,aAAA,EAAe,CAAC,oBAAoB,CAAC,EAAE,QAAA,EAAS;AAAA,EAC5E,OAAA,EAASA,EAAE,kBAAA,CAAmB,aAAA,EAAe,CAAC,eAAe,CAAC,EAAE,QAAA,EAAS;AAAA,EACzE,KAAA,EAAOA,EAAE,kBAAA,CAAmB,aAAA,EAAe,CAAC,mBAAmB,CAAC,EAAE,QAAA,EAAS;AAAA,EAC3E,GAAA,EAAKA,EAAE,kBAAA,CAAmB,aAAA,EAAe,CAAC,sBAAsB,CAAC,EAAE,QAAA;AACrE,CAAC,EAAE,QAAA,EAAS;AAcL,IAAM,kBAAA,GAAqBA,EAAE,MAAA,CAAO;AAAA;AAAA,EAEzC,WAAA,EAAaA,EAAE,MAAA,EAAO,CAAE,MAAM,mBAAmB,CAAA,CAAE,OAAO,CAAA,KAAA,KAAS,CAAC,CAAC,OAAA,EAAS,SAAS,EAAE,QAAA,CAAS,KAAA,CAAM,aAAa,CAAC,EAAE,QAAA,EAAS;AAAA,EACjI,QAAA,EAAU,oBAAA;AAAA,EACV,QAAA,EAAU,oBAAA;AAAA;AAAA,EAEV,SAAA,EAAWA,EAAE,MAAA,CAAO;AAAA;AAAA,IAElB,QAAA,EAAUA,EAAE,IAAA,CAAK,CAAC,UAAU,OAAO,CAAC,CAAA,CAAE,OAAA,CAAQ,QAAQ;AAAA,GACvD,EAAE,QAAA;AACL,CAAC;ACtND,IAAM,eAAA,GAAkB;AAAA,EACtB,aAAA,EAAe,SAAA;AAAA,EACf,qBAAA,EAAuB,SAAA;AAAA,EACvB,aAAA,EAAe,SAAA;AAAA,EACf,aAAA,EAAe,SAAA;AAAA,EACf,WAAA,EAAa,SAAA;AAAA,EACb,gBAAA,EAAkB,SAAA;AAAA,EAClB,eAAA,EAAiB,SAAA;AAAA,EACjB,WAAA,EAAa,SAAA;AAAA,EACb,eAAA,EAAiB,SAAA;AAAA,EACjB,cAAA,EAAgB,SAAA;AAAA,EAChB,gBAAA,EAAkB,SAAA;AAAA,EAClB,YAAA,EAAc,SAAA;AAAA,EACd,gBAAA,EAAkB,SAAA;AAAA,EAClB,qBAAA,EAAuB,SAAA;AAAA,EACvB,qBAAA,EAAuB,SAAA;AAAA,EACvB,qBAAA,EAAuB,SAAA;AAAA,EACvB,mBAAA,EAAqB;AACvB,CAAA;AAcO,IAAM,cAAA,GAAiBC,IAAAA,CAAK,KAAA,CAAM,iBAAA,CAAkB,UAAU,eAAe;;;ACZpF,SAAS,iBAAiB,KAAA,EAAwB;AAChD,EAAA,IAAI;AACF,IAAA,OAAO,KAAA,CAAM,KAAK,CAAA,IAAK,KAAA;AAAA,EACzB,CAAA,CAAA,MACM;AACJ,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,IAAM,UAAA,GAAa,yBAAA;AACnB,IAAM,cAAc,oBAAA,CAAqB,OAAA,CAAQ,KAAK,CAAA,QAAA,KAAY,KAAA,IAAS,SAAS,KAAK,CAAA;AAEzF,IAAM,SAAA,GAAY,IAAI,GAAA,CAAI,WAAA,IAAe,KAAA,IAAS,WAAA,CAAY,KAAA,GAC1D,MAAA,CAAO,IAAA,CAAK,WAAA,CAAY,KAAA,CAAM,GAAA,CAAI,MAAA,GAAS,KAAK,CAAA,CAAE,GAAA,CAAI,CAAA,IAAA,KAAQ,CAAC,IAAA,CAAK,WAAA,EAAY,EAAG,IAAI,CAAC,CAAA,GACxF,EAAE,CAAA;AACN,IAAM,mCAAmB,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,uBAAA,EAAyB,uBAAuB,CAAC,CAAA;AAG3F,SAAS,cAAc,KAAA,EAAgB,MAAA,EAAgB,KAAyC,UAAA,GAAa,KAAA,EAAO,UAAU,KAAA,EAAgB;AAC5I,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,UAAA,CAAW,CAAA,EAAG,UAAU,CAAA,CAAA,CAAG,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,UAAA,CAAW,MAAA,GAAS,CAAC,CAAA,GAAI,MAAA;AAC7F,EAAA,MAAM,YAAA,GAAe,QAAA,KAAa,MAAA,IAAa,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA,IAAK,CAAC,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAA;AACxG,EAAA,IAAI,GAAA,CAAI,MAAM,CAAA,KAAM,MAAA,EAAW;AAC7B,IAAA,IAAI,UAAA,IAAc,YAAA;AAChB,MAAA,OAAO,IAAI,MAAM,CAAA;AACnB,IAAA,IAAI,CAAC,UAAA;AACH,MAAA,OAAO,gBAAA,CAAiB,GAAA,CAAI,MAAM,CAAC,CAAA;AACrC,IAAA,KAAA,GAAQ,gBAAA,CAAiB,GAAA,CAAI,MAAM,CAAC,CAAA;AAEpC,IAAA,OAAA,GAAU,IAAA;AAAA,EACZ;AACA,EAAA,IAAI,KAAA,CAAM,QAAQ,KAAK,CAAA;AACrB,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,UAAU,aAAA,CAAc,IAAA,EAAM,CAAA,EAAG,MAAM,IAAI,KAAK,CAAA,CAAA,EAAI,GAAA,EAAK,UAAA,EAAY,OAAO,CAAC,CAAA;AACvG,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACtC,IAAA,MAAM,KAAA,GAAiC,EAAE,GAAG,KAAA,EAAM;AAClD,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,WAAA,GAAc,IAAI,UAAU,CAAA,KAAM,UAAa,CAAC,GAAG,UAAU,IAAA,EAAM,EAAE,IAAA,CAAK,CAAAC,WAAS,GAAA,CAAI,CAAA,EAAG,UAAU,CAAA,CAAA,EAAIA,MAAK,CAAA,CAAE,CAAA,KAAM,MAAS,CAAA;AACpI,MAAA,IAAI,WAAA,IAAe,MAAA,KAAW,YAAA,IAAgB,KAAA,CAAM,QAAA,KAAa,MAAA;AAC/D,QAAA,KAAA,CAAM,WAAW,EAAC;AACpB,MAAA,IAAI,WAAA,IAAe,MAAA,KAAW,qBAAA,IAAyB,KAAA,CAAM,GAAA,KAAQ,MAAA;AACnE,QAAA,KAAA,CAAM,MAAM,EAAC;AACf,MAAA,IAAI,WAAW,UAAA,EAAY;AACzB,QAAA,KAAA,MAAW,CAACA,MAAAA,EAAO,IAAI,CAAA,IAAK,SAAA,EAAW;AACrC,UAAA,IAAI,GAAA,CAAI,GAAG,UAAU,CAAA,CAAA,EAAIA,MAAK,CAAA,CAAE,CAAA,KAAM,MAAA,IAAa,EAAE,IAAA,IAAQ,KAAA,CAAA;AAC3D,YAAA,KAAA,CAAM,IAAI,CAAA,GAAI,MAAA;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,MAAM,CAAA,KAAM,CAAC,GAAA,EAAK,aAAA,CAAc,MAAA,EAAQ,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,GAAA,CAAI,WAAA,EAAa,CAAA,CAAA,EAAI,GAAA,EAAK,UAAA,EAAY,OAAO,CAAC,CAAC,CAAC,CAAA;AAAA,EAClK;AACA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA;AACnB,IAAA,OAAO,KAAA;AACT,EAAA,IAAI,OAAA;AACF,IAAA,OAAO,KAAA;AACT,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,OAAA,CAAQ,8BAAA,EAAgC,CAAC,MAAA,EAAQ,IAAA,EAAc,QAAA,KAAsB,GAAA,CAAI,IAAI,CAAA,IAAK,QAAA,IAAY,EAAE,CAAA;AACvI,EAAA,OAAO,eAAA,CAAgB,KAAK,KAAK,CAAA,IAAK,CAAC,YAAA,GAAe,gBAAA,CAAiB,QAAQ,CAAA,GAAI,QAAA;AACrF;AAGA,SAAS,gBAAgB,IAAA,EAAsC;AAC7D,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,IAAIC,UAAAA,CAAW,IAAI,CAAA,EAAG;AACpB,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,QAAA,CAASC,YAAAA,CAAa,IAAA,EAAM,MAAM,CAAC,CAAC,CAAA,EAAG;AAChF,MAAA,IAAI,KAAA,KAAU,MAAA;AACZ,QAAA,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA;AAAA,IACnB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAYO,SAAS,sBAAA,CAAuB,QAAmD,MAAA,EAAyC;AACjI,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,OAAO,CAAA,IAAA,KAAQ,CAAC,MAAA,IAAU,IAAA,KAAS,MAAA,IAAU,IAAA,CAAK,WAAW,CAAA,EAAG,MAAM,CAAA,CAAA,CAAG,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,EAAM,KAAA,KAAU,IAAA,CAAK,MAAA,GAAS,KAAA,CAAM,MAAM,CAAA;AAC7J,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAI,CAAA;AACxB,MAAA,IAAI,KAAA,KAAU,MAAA;AACZ,QAAA;AACF,MAAA,IAAI,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,EAAG;AAC3B,QAAA,KAAA,MAAW,QAAA,IAAY,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AAC1C,UAAA,IAAI,QAAA,CAAS,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA;AAChC,YAAA,OAAO,OAAO,QAAQ,CAAA;AAAA,QAC1B;AAAA,MACF;AACA,MAAA,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA;AAAA,IACjB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAmBO,SAAS,oBAAA,CAAqB,IAAA,EAAc,IAAA,EAAc,MAAA,EAAgF;AAC/I,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAUA,YAAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AACzC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI,OAAA,CAAQ,IAAI,CAAA,CAAE,WAAA,OAAkB,OAAA,EAAS;AAC3C,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAC3C,QAAA,KAAA,GAAQ,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,GAAK,OAAA,CAAoC,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,MAC3H,CAAA,CAAA,MACM;AACJ,QAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,0BAAA,EAA4B,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,GAAA,EAAI,EAAG,CAAC,CAAA;AAAA,MAC9G;AACA,MAAA,IAAI,CAAC,KAAA,IAAS,OAAO,UAAU,QAAA,IAAY,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5D,QAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,0BAAA,EAA4B,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,GAAA,EAAI,EAAG,CAAC,CAAA;AAAA,IAChH,CAAA,MACK;AACH,MAAA,MAAM,WAAA,GAAc,IAAI,WAAA,EAAY;AACpC,MAAA,MAAM,WAAW,aAAA,CAAc,OAAA,EAAS,EAAE,WAAA,EAAa,YAAA,EAAc,OAAO,CAAA;AAC5E,MAAA,IAAI,SAAS,MAAA,CAAO,MAAA;AAClB,QAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,0BAAA,EAA4B,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,WAAA,CAAY,QAAQ,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,CAAG,GAAA,CAAI,CAAC,CAAC,CAAA,CAAE,IAAI,CAAA,EAAE,EAAG,CAAC,CAAA;AACvK,MAAA,KAAA,GAAQ,SAAS,IAAA,EAAK;AAAA,IACxB;AACA,IAAA,MAAM,MAAA,GAAS,aAAA,CAAc,KAAA,EAAO,CAAA,IAAA,EAAO,IAAA,CAAK,aAAa,CAAA,CAAA,EAAI,MAAA,EAAQ,IAAA,KAAS,QAAQ,CAAA;AAC1F,IAAA,IAAI,WAAW,IAAA,KAAS,OAAO,WAAW,QAAA,IAAY,KAAA,CAAM,QAAQ,MAAM,CAAA,CAAA;AACxE,MAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,0BAAA,EAA4B,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,GAAA,EAAI,EAAG,CAAC,CAAA;AAC9G,IAAA,OAAO,EAAA,CAAG,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GAAI,MAAA,GAAoC,EAAE,CAAA;AAAA,EACnH,CAAA,CAAA,MACM;AACJ,IAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,6BAAA,EAA+B,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAK,EAAG,CAAC,CAAA;AAAA,EACtG;AACF;AAmBO,SAAS,0BAA0B,OAAA,EAA2G;AACnJ,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,KAAgB,YAAA,GAAe,SAAS,OAAA,CAAQ,WAAA,KAAgB,aAAA,GAAgB,KAAA,GAAQ,OAAA,CAAQ,WAAA;AAC5H,EAAA,IAAI,CAAC,mBAAA,CAAoB,IAAA,CAAK,WAAW,CAAA,IAAK,CAAC,OAAA,EAAS,SAAS,CAAA,CAAE,QAAA,CAAS,WAAA,CAAY,WAAA,EAAa,CAAA;AACnG,IAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,2BAA2B,CAAC,CAAA;AAC9E,EAAA,MAAM,MAAA,GAASC,OAAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AACrC,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,EAAQ,CAAA,KAAA,EAAQ,WAAW,CAAA,CAAE,CAAA;AACjD,EAAA,IAAI,OAAA,CAAQ,WAAA,KAAgB,KAAA,IAAS,CAACF,WAAW,MAAM,CAAA;AACrD,IAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,2BAAA,EAA6B,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,MAAA,EAAO,EAAG,CAAC,CAAA;AAC5G,EAAA,MAAM,MAAA,GAASF,KAAK,MAAA,CAAO,YAAA,CAAa,EAAE,IAAA,EAAM,WAAA,EAAa,QAAQ,CAAA;AACrE,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA;AACV,IAAA,OAAO,MAAA;AACT,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAC,CAAA;AACjD,IAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,IAAA,CAAK,MAAA,EAAQ,YAAY,CAAC,CAAA;AAChE,IAAA,MAAM,QAAA,GAAW,gBAAgB,MAAM,CAAA;AACvC,IAAA,MAAM,cAAc,eAAA,CAAgB,IAAA,CAAK,QAAQ,CAAA,KAAA,EAAQ,WAAW,QAAQ,CAAC,CAAA;AAC7E,IAAA,MAAM,SAAS,EAAE,GAAG,MAAA,CAAO,IAAA,EAAM,GAAG,WAAA,EAAY;AAEhD,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACtC,MAAA,IAAIK,QAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,KAAM,KAAA,CAAA;AACxB,QAAA,MAAA,CAAO,IAAI,CAAA,GAAIA,QAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAAA,IACnC;AAEA,IAAA,KAAA,MAAW,CAAC,MAAM,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQA,QAAA,CAAQ,GAAG,CAAA,EAAG;AACvD,MAAA,IAAI,yBAAA,CAA0B,IAAA,CAAK,IAAI,CAAA,IAAK,KAAA,KAAU,KAAA,CAAA;AACpD,QAAA,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA;AAAA,IACnB;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACtC,MAAA,IAAI,IAAA,KAAS,YAAA,IAAgB,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA;AACxD,QAAA,OAAO,OAAO,IAAI,CAAA;AAAA,IACtB;AACA,IAAA,MAAA,CAAO,MAAA,CAAO,MAAA,EAAQ,sBAAA,CAAuB,CAAC,IAAA,EAAM,aAAA,EAAe,QAAA,EAAU,WAAA,EAAaA,QAAA,CAAQ,GAAG,CAAA,EAAG,YAAY,CAAC,CAAA;AACrH,IAAA,MAAA,CAAO,sBAAA,GAAyB,WAAA;AAChC,IAAA,MAAA,CAAO,YAAA,KAAiB,gBAAgB,MAAA,GAAS,YAAA,GAAe,gBAAgB,KAAA,GAAQ,aAAA,GAAgB,WAAA,KAAgB,MAAA,GAAS,MAAA,GAAS,SAAA;AAC1I,IAAA,OAAO,GAAG,EAAE,WAAA,EAAa,QAAQ,MAAA,EAAQ,YAAA,EAAc,UAAU,CAAA;AAAA,EACnE,CAAA,CAAA,MACM;AACJ,IAAA,OAAO,GAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,8BAA8B,CAAC,CAAA;AAAA,EACjF;AACF;AAGA,SAAS,QAAA,CAAS,MAAc,KAAA,EAAwB;AACtD,EAAA,IAAI,kEAAA,CAAmE,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,eAAe,EAAE,CAAC,CAAA,IAAK,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,IAAK,KAAA,CAAM,SAAS,aAAa,CAAA;AACxK,IAAA,OAAO,IAAA;AACT,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,KAAK,CAAA;AACzB,IAAA,IAAI,IAAI,QAAA,IAAY,GAAA,CAAI,QAAA,IAAY,CAAC,GAAG,GAAA,CAAI,YAAA,CAAa,IAAA,EAAM,EAAE,IAAA,CAAK,CAAA,GAAA,KAAO,0CAAA,CAA2C,IAAA,CAAK,GAAG,CAAC,CAAA;AAC/H,MAAA,OAAO,IAAA;AAAA,EACX,CAAA,CAAA,MACM;AAAA,EAAyB;AAC/B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACxC,IAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA;AAC9B,MAAA,OAAO,MAAA,CAAO,QAAQ,MAAM,CAAA,CAAE,KAAK,CAAC,CAAC,KAAK,MAAM,CAAA,KAAM,SAAS,GAAA,EAAK,OAAO,WAAW,QAAA,GAAW,MAAA,GAAS,KAAK,SAAA,CAAU,MAAM,CAAC,CAAC,CAAA;AAAA,EACrI,CAAA,CAAA,MACM;AAAA,EAAyB;AAC/B,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,aAAa,KAAA,EAAyB;AAC7C,EAAA,IAAI,KAAA,CAAM,QAAQ,KAAK,CAAA;AACrB,IAAA,OAAO,KAAA,CAAM,IAAI,YAAY,CAAA;AAC/B,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA;AAC5B,IAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,CAAC,MAAM,IAAI,CAAA,KAAM,CAAC,QAAA,CAAS,MAAM,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,EAAE,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,IAAA,EAAM,IAAI,CAAA,KAAM,CAAC,IAAA,EAAM,YAAA,CAAa,IAAI,CAAC,CAAC,CAAC,CAAA;AACnL,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,SAAS,KAAA,EAAuB;AAEvC,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACxC,IAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA;AAC9B,MAAA,OAAO,CAAA,CAAA,EAAI,KAAK,SAAA,CAAU,MAAM,EAAE,UAAA,CAAW,GAAA,EAAM,SAAS,CAAC,CAAA,CAAA,CAAA;AAAA,EACjE,CAAA,CAAA,MACM;AAAA,EAA6B;AACnC,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,GAAI,CAAA;AACtB,IAAA,OAAO,IAAI,KAAK,CAAA,CAAA,CAAA;AAClB,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA;AACrB,IAAA,OAAO,IAAI,KAAK,CAAA,CAAA,CAAA;AAClB,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA;AACrB,IAAA,OAAO,KAAK,KAAK,CAAA,EAAA,CAAA;AACnB,EAAA,IAAI,CAAC,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA;AACvB,IAAA,OAAO,KAAA;AACT,EAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAC5C;AAGA,SAAS,UAAA,CAAW,IAAA,EAAc,MAAA,EAAgCC,YAAAA,EAA4B;AAC5F,EAAA,IAAI,UAAUJ,UAAAA,CAAW,IAAI,IAAIC,YAAAA,CAAa,IAAA,EAAM,MAAM,CAAA,GAAI,4DAAA;AAC9D,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClD,IAAA,IAAI,CAAC,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAChC,MAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AACrD,IAAA,MAAM,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAA,CAAS,KAAK,CAAC,CAAA,CAAA;AAEvC,IAAA,MAAM,UAAU,IAAI,MAAA,CAAO,CAAA,gBAAA,EAAmB,IAAI,gEAAgE,IAAI,CAAA;AACtH,IAAA,IAAI,OAAA,CAAQ,KAAK,OAAO,CAAA;AACtB,MAAA,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,OAAA,EAAS,MAAM,IAAI,CAAA;AAAA;AAE7C,MAAA,OAAA,GAAU,CAAA,EAAG,OAAA,CAAQ,OAAA,EAAS;AAAA,EAAK,IAAI;AAAA,CAAA;AAAA,EAC3C;AACA,EAAA,aAAA,CAAc,MAAM,OAAA,EAAS,EAAE,MAAMG,YAAAA,GAAc,GAAA,GAAQ,KAAO,CAAA;AAClE,EAAA,IAAIA,YAAAA;AACF,IAAA,SAAA,CAAU,MAAM,GAAK,CAAA;AACzB;AAGA,SAAS,eAAA,CAAgB,IAAA,EAAc,KAAA,EAAiBA,YAAAA,GAAc,IAAA,EAAY;AAChF,EAAA,IAAI,CAACJ,UAAAA,CAAW,IAAI,CAAA,IAAK,MAAM,MAAA,KAAW,CAAA;AACxC,IAAA;AACF,EAAA,IAAI,OAAA,GAAUC,YAAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AACvC,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA;AACjB,IAAA,OAAA,GAAU,OAAA,CAAQ,QAAQ,IAAI,MAAA,CAAO,mBAAmB,IAAI,CAAA,yEAAA,CAAA,EAA6E,IAAI,CAAA,EAAG,EAAE,CAAA;AACpJ,EAAA,aAAA,CAAc,MAAM,OAAA,EAAS,EAAE,MAAMG,YAAAA,GAAc,GAAA,GAAQ,KAAO,CAAA;AAClE,EAAA,SAAA,CAAU,IAAA,EAAMA,YAAAA,GAAc,GAAA,GAAQ,GAAK,CAAA;AAC7C;AAoBO,SAAS,yBAAA,CAA0B,WAAA,EAAoC,MAAA,EAAgC,OAAA,GAAiC,EAAC,EAAwB;AACtK,EAAA,IAAI;AACF,IAAA,MAAM,SAAiC,EAAC;AACxC,IAAA,MAAM,gBAAwC,EAAC;AAC/C,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClD,MAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,QAAA,aAAA,CAAc,IAAI,CAAA,GAAI,KAAA;AAAA,MACxB,CAAA,MAAA,IACS,QAAA,CAAS,IAAA,EAAM,KAAK,CAAA,EAAG;AAC9B,QAAA,aAAA,CAAc,IAAI,CAAA,GAAI,KAAA;AACtB,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACxC,UAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA;AAC9B,YAAA,MAAA,CAAO,IAAI,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,MAAM,CAAC,CAAA;AAAA,QACtD,CAAA,CAAA,MACM;AAAA,QAAoB;AAAA,MAC5B,CAAA,MACK;AACH,QAAA,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA;AAAA,MACjB;AAAA,IACF;AACA,IAAA,MAAM,cAAc,IAAA,CAAK,WAAA,CAAY,QAAQ,CAAA,KAAA,EAAQ,WAAA,CAAY,WAAW,CAAA,MAAA,CAAQ,CAAA;AACpF,IAAA,MAAM,gBAAgB,eAAA,CAAgB,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,YAAY,CAAC,CAAA;AAE5E,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClD,MAAA,IAAI,EAAE,IAAA,IAAQ,aAAA,CAAA,IAAkB,aAAA,CAAc,IAAI,CAAA,KAAM,KAAA,CAAA,IAAa,IAAA,KAAS,YAAA,IAAgB,CAAC,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA;AAC1H,QAAA,aAAA,CAAc,IAAI,CAAA,GAAI,KAAA;AAAA,IAC1B;AACA,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA;AACtB,MAAA,UAAA,CAAW,IAAA,CAAK,YAAY,MAAA,EAAQ,CAAA,KAAA,EAAQ,YAAY,WAAW,CAAA,CAAE,CAAA,EAAG,MAAA,EAAQ,KAAK,CAAA;AACvF,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,CAAE,MAAA;AAC7B,MAAA,UAAA,CAAW,WAAA,EAAa,eAAe,IAAI,CAAA;AAC7C,IAAA,eAAA,CAAgB,KAAK,WAAA,CAAY,MAAA,EAAQ,QAAQ,WAAA,CAAY,WAAW,EAAE,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,aAAa,EAAE,MAAA,CAAO,CAAA,IAAA,KAAQ,EAAE,IAAA,IAAQ,MAAA,CAAO,GAAG,KAAK,CAAA;AAChJ,IAAA,eAAA,CAAgB,WAAA,EAAa,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAO,CAAA,IAAA,KAAQ,EAAE,IAAA,IAAQ,aAAA,CAAc,CAAC,CAAA;AACzF,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,CAAE,MAAA,EAAQ;AACrC,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,YAAY,CAAA;AACxD,MAAA,MAAM,SAASJ,UAAAA,CAAW,UAAU,IAAIC,YAAAA,CAAa,UAAA,EAAY,MAAM,CAAA,GAAI,EAAA;AAC3E,MAAA,MAAM,OAAA,GAAU,CAAC,YAAA,EAAc,cAAA,EAAgB,cAAc,CAAA,CAAE,MAAA,CAAO,CAAA,IAAA,KAAQ,CAAC,OAAO,KAAA,CAAM,OAAO,CAAA,CAAE,QAAA,CAAS,IAAI,CAAC,CAAA;AACnH,MAAA,IAAI,OAAA,CAAQ,MAAA;AACV,QAAA,aAAA,CAAc,UAAA,EAAY,CAAA,EAAG,MAAA,CAAO,OAAA,EAAS;AAAA,EAAK,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC;AAAA,CAAI,CAAA;AAAA,IAC5E;AACA,IAAA,OAAO,EAAA,CAAG,MAAA,CAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,EAC/B,CAAA,CAAA,MACM;AACJ,IAAA,OAAO,GAAA,CAAI,cAAA,CAAe,cAAA,EAAgB,OAAA,CAAQ,+BAA+B,CAAC,CAAA;AAAA,EACpF;AACF;ACtWO,SAAS,qBAAqB,IAAA,EAAsB;AACzD,EAAA,MAAM,aAAa,IAAA,CAAK,IAAA,EAAK,CAAE,OAAA,CAAQ,aAAa,EAAE,CAAA,CAAE,WAAA,EAAY,CAAE,QAAQ,cAAA,EAAgB,GAAG,CAAA,CAAE,OAAA,CAAQ,YAAY,EAAE,CAAA;AACzH,EAAA,IAAI,CAAC,UAAA;AACH,IAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,4BAA4B,CAAC,CAAA;AACvD,EAAA,OAAO,UAAA;AACT;AAaO,SAAS,wBAAwB,MAAA,EAAwB;AAC9D,EAAA,IAAI,SAAA,GAAYC,QAAQ,MAAM,CAAA;AAC9B,EAAA,OAAO,IAAA,EAAM;AACX,IAAA,IAAIF,UAAAA,CAAWK,IAAAA,CAAK,SAAA,EAAW,UAAU,CAAC,KAAKL,UAAAA,CAAWK,IAAAA,CAAK,SAAA,EAAW,gBAAgB,CAAC,CAAA;AACzF,MAAA,OAAO,SAAA;AACT,IAAA,MAAM,MAAA,GAAS,QAAQ,SAAS,CAAA;AAChC,IAAA,IAAI,MAAA,KAAW,SAAA;AACb,MAAA,OAAOH,QAAQ,MAAM,CAAA;AACvB,IAAA,SAAA,GAAY,MAAA;AAAA,EACd;AACF;AAWO,SAAS,yBAAyB,MAAA,EAAwB;AAC/D,EAAA,OAAOG,IAAAA,CAAK,uBAAA,CAAwB,MAAM,CAAA,EAAG,mBAAmB,CAAA;AAClE;AAcO,SAAS,qBAAA,CAAsB,IAAA,EAAkB,OAAA,EAAsB,OAAA,EAAqC;AACjH,EAAA,MAAM,YAAA,GAAe,KAAK,WAAA,EAAa,MAAA,CAAO,UAAQ,IAAA,CAAK,OAAA,KAAY,OAAO,CAAA,IAAK,EAAC;AACpF,EAAA,OAAO,YAAA,CAAa,SAChB,YAAA,CAAa,IAAA,CAAK,WAAS,OAAA,EAAS,YAAA,GAAe,KAAK,SAAS,CAAA,IAAK,SAAS,YAAA,GAAe,OAAO,KAAK,SAAA,MAAe,SAAS,KACjI,OAAA,EAAS,YAAA,GAAe,OAAO,CAAA,IAAK,SAAA,MAAe,SAAA;AAC1D;AAYO,SAAS,gBAAA,CAAiB,QAAgB,YAAA,EAA8B;AAC7E,EAAA,QAAQ,YAAA;AAAc,IACpB,KAAK,QAAA;AACH,MAAA,OAAOA,IAAAA,CAAK,MAAA,EAAQ,SAAA,EAAW,QAAQ,CAAA;AAAA,IACzC;AACE,MAAA,OAAOA,IAAAA,CAAK,QAAQ,OAAO,CAAA;AAAA;AAEjC;ACnFA,IAAM,MAAA,GAASP,KAAK,MAAA,CAAO,KAAA,CAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,aAAA,EAAe,CAAA;AAG3E,IAAM,6BAAA,GAAgC,yBAAA;AAKtC,SAAS,uBAAuB,GAAA,EAAsB;AACpD,EAAA,OAAO,6BAAA,CAA8B,KAAK,GAAG,CAAA;AAC/C;AAOA,SAAS,2BAA2B,OAAA,EAA0D;AAC5F,EAAA,MAAM,aAAqC,EAAC;AAE5C,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAClD,IAAA,IAAI,CAAC,sBAAA,CAAuB,GAAG,CAAA,EAAG;AAChC,MAAA,MAAA,CAAO,IAAA,CAAK,4CAAA,EAA8C,EAAE,GAAA,EAAK,CAAA;AACjE,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,SAAA,EAAW;AACxF,MAAA,UAAA,CAAW,GAAG,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAC9B,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,IAAA,CAAK,kDAAA,EAAoD,EAAE,GAAA,EAAK,CAAA;AAAA,EACzE;AAEA,EAAA,OAAO,UAAA;AACT;AAGA,SAAS,2BAA2B,GAAA,EAAmB;AACrD,EAAA,IAAI,CAAC,sBAAA,CAAuB,GAAG,CAAA,EAAG;AAChC,IAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,6BAAA,EAA+B,EAAE,QAAQ,EAAE,GAAA,EAAI,EAAG,CAAC,CAAA;AAAA,EAC7E;AACF;AAGA,SAAS,+BAA+B,OAAA,EAAuC;AAC7E,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG;AACtC,IAAA,0BAAA,CAA2B,GAAG,CAAA;AAAA,EAChC;AACF;AAUO,SAAS,kBAAA,GAA6B;AAC3C,EAAA,OAAOO,IAAAA,CAAK,OAAA,EAAQ,EAAG,MAAA,EAAQ,iBAAiB,CAAA;AAClD;AAOA,SAAS,UAAU,QAAA,EAAwB;AACzC,EAAA,MAAM,GAAA,GAAMC,QAAQ,QAAQ,CAAA;AAC5B,EAAA,IAAI,CAACN,UAAAA,CAAW,GAAG,CAAA,EAAG;AACpB,IAAA,SAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,EACpC;AACF;AAOA,SAAS,mBAAA,GAA8C;AACrD,EAAA,MAAM,WAAW,kBAAA,EAAmB;AACpC,EAAA,IAAI,CAACA,UAAAA,CAAW,QAAQ,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,OAAA,GAAUC,YAAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC9C,EAAA,MAAM,MAAA,GAASM,MAAM,OAAO,CAAA;AAC5B,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,IAAa,OAAO,WAAW,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClG,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,OAAO,2BAA2B,MAAiC,CAAA;AACrE;AAOA,SAAS,qBAAqB,IAAA,EAAoC;AAChE,EAAA,MAAM,WAAW,kBAAA,EAAmB;AACpC,EAAA,SAAA,CAAU,QAAQ,CAAA;AAClB,EAAA,MAAM,MAAA,GAAS,+CAAA;AACf,EAAA,MAAM,OAAA,GAAU,MAAA,GAAS,SAAA,CAAU,IAAI,CAAA;AACvC,EAAAC,aAAAA,CAAc,UAAU,OAAA,EAAS,EAAE,UAAU,OAAA,EAAS,IAAA,EAAM,KAAO,CAAA;AACrE;AAkBO,SAAS,eAAA,GAAuC;AACrD,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,mBAAA,EAAoB;AACjC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAC7B,IAAA,MAAM,aAAa,MAAA,CAAO,IAAA,CAAKL,QAAAA,CAAQ,GAAG,EAAE,MAAA,CAAO,CAAA,GAAA,KAAA,CAAQ,GAAA,KAAQ,YAAA,IAAgB,uBAAuB,GAAG,CAAA,KAAMA,SAAQ,GAAA,CAAI,GAAG,MAAM,KAAA,CAAS,CAAA;AACjJ,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,CAAA,IAAA,KAAQ,GAAA,KAAQ,IAAA,IAAQ,GAAA,CAAI,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAC,CAAA;AACrE,QAAAA,SAAQ,GAAA,CAAI,GAAG,IAAI,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IACvC;AACA,IAAA,MAAA,CAAO,MAAM,oBAAA,EAAsB,EAAE,KAAA,EAAO,IAAA,CAAK,QAAQ,CAAA;AACzD,IAAA,OAAOM,GAAG,IAAI,CAAA;AAAA,EAChB,SACO,KAAA,EAAO;AACZ,IAAA,MAAA,CAAO,KAAA,CAAM,4BAAA,EAA8B,EAAE,KAAA,EAAO,CAAA;AACpD,IAAA,OAAOC,GAAAA;AAAA,MACL,cAAA,CAAe,gBAAA;AAAA,MACf,QAAQ,wBAAA,EAA0B;AAAA,QAChC,MAAA,EAAQ,EAAE,KAAA,EAAO,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA;AAAE,OACzE,CAAA;AAAA,MACD;AAAA,KACF;AAAA,EACF;AACF;AAkBO,SAAS,cAAA,CAAe,KAAa,KAAA,EAAgC;AAC1E,EAAA,IAAI;AACF,IAAA,0BAAA,CAA2B,GAAG,CAAA;AAC9B,IAAA,MAAM,OAAO,mBAAA,EAAoB;AACjC,IAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AACZ,IAAA,oBAAA,CAAqB,IAAI,CAAA;AACzB,IAAAP,QAAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AACnB,IAAA,MAAA,CAAO,KAAA,CAAM,kBAAA,EAAoB,EAAE,GAAA,EAAK,CAAA;AACxC,IAAA,OAAOM,GAAG,KAAA,CAAS,CAAA;AAAA,EACrB,SACO,KAAA,EAAO;AACZ,IAAA,MAAA,CAAO,KAAA,CAAM,2BAAA,EAA6B,EAAE,GAAA,EAAK,OAAO,CAAA;AACxD,IAAA,OAAOC,GAAAA;AAAA,MACL,cAAA,CAAe,gBAAA;AAAA,MACf,QAAQ,wBAAA,EAA0B;AAAA,QAChC,MAAA,EAAQ,EAAE,KAAA,EAAO,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA;AAAE,OACzE,CAAA;AAAA,MACD;AAAA,KACF;AAAA,EACF;AACF;AAcO,SAAS,gBAAgB,OAAA,EAAkD;AAChF,EAAA,IAAI;AACF,IAAA,8BAAA,CAA+B,OAAO,CAAA;AACtC,IAAA,MAAM,OAAO,mBAAA,EAAoB;AACjC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAClD,MAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AACZ,MAAAP,QAAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,IACrB;AACA,IAAA,oBAAA,CAAqB,IAAI,CAAA;AACzB,IAAA,MAAA,CAAO,KAAA,CAAM,qBAAqB,EAAE,KAAA,EAAO,OAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,EAAQ,CAAA;AACxE,IAAA,OAAOM,GAAG,KAAA,CAAS,CAAA;AAAA,EACrB,SACO,KAAA,EAAO;AACZ,IAAA,MAAA,CAAO,KAAA,CAAM,4BAAA,EAA8B,EAAE,KAAA,EAAO,CAAA;AACpD,IAAA,OAAOC,GAAAA;AAAA,MACL,cAAA,CAAe,gBAAA;AAAA,MACf,QAAQ,wBAAA,EAA0B;AAAA,QAChC,MAAA,EAAQ,EAAE,KAAA,EAAO,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA;AAAE,OACzE,CAAA;AAAA,MACD;AAAA,KACF;AAAA,EACF;AACF;;;ACzOA,IAAM,gBAAA,GAAoE;AAAA,EACxE,EAAA,EAAI,CAAC,KAAA,EAAO,MAAA,EAAQ,QAAQ,UAAA,EAAY,MAAA,EAAQ,YAAY,KAAK,CAAA;AAAA,EACjE,KAAA,EAAO,CAAC,KAAA,EAAO,MAAA,EAAQ,QAAQ,UAAA,EAAY,SAAA,EAAW,YAAY,KAAK,CAAA;AAAA,EACvE,OAAA,EAAS,CAAC,UAAA,EAAY,QAAA,EAAU,UAAU,aAAA,EAAe,iBAAA,EAAmB,kBAAkB,cAAc,CAAA;AAAA,EAC5G,KAAA,EAAO,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAU,MAAA,EAAQ,eAAA,EAAiB,gBAAgB,CAAA;AAAA,EAClH,MAAM,CAAC,KAAA,EAAO,QAAA,EAAU,cAAA,EAAgB,cAAc,QAAQ,CAAA;AAAA,EAC9D,OAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,QAAQ,MAAM;AAClD,CAAA;AAaO,SAAS,4BAAA,CAA6B,aAAgD,QAAA,EAA4D;AACvJ,EAAA,IAAI,CAAC,WAAA,IAAgB,WAAA,CAAY,YAAY,MAAA,IAAU,WAAA,CAAY,YAAY,QAAA,CAAS,IAAA;AACtF,IAAA,OAAO,QAAA;AACT,EAAA,MAAM,UAAA,GAAa,EAAE,GAAG,WAAA,CAAY,MAAA,EAAO;AAC3C,EAAA,KAAA,MAAWX,MAAAA,IAAS,gBAAA,CAAiB,WAAA,CAAY,OAAO,KAAK,EAAC;AAC5D,IAAA,OAAO,WAAWA,MAAK,CAAA;AACzB,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,UAAA,EAAY,GAAG,QAAA,EAAS;AAE5C,EAAA,IAAI,WAAA,CAAY,OAAA,KAAY,OAAA,IAAW,OAAO,UAAA,CAAW,OAAO,QAAA,IAAY,OAAO,QAAA,CAAS,GAAA,KAAQ,QAAA,EAAU;AAC5G,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA;AAChC,IAAA,IAAI,UAAA,CAAW,OAAO,CAAA,IAAM,GAAA,CAAI,aAAa,EAAA,IAAM,GAAA,CAAI,aAAa,GAAA,EAAM;AACxE,MAAA,GAAA,CAAI,QAAA,GAAW,MAAA,CAAO,UAAA,CAAW,EAAE,CAAA;AACnC,MAAA,MAAA,CAAO,GAAA,GAAM,IAAI,QAAA,EAAS;AAAA,IAC5B;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AClCA,IAAM,cAAA,GAAiBF,EAAE,MAAA,CAAO;AAAA,EAC9B,WAAA,EAAaA,EAAE,MAAA,EAAO;AAAA,EACtB,KAAA,EAAOA,EAAE,MAAA,EAAO;AAAA,EAChB,iBAAA,EAAmBA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACvC,SAAA,EAAWA,CAAAA,CAAE,KAAA,CAAMA,CAAAA,CAAE,MAAA,CAAO;AAAA,IAC1B,WAAA,EAAaA,EAAE,IAAA,CAAK,CAAC,MAAM,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,KAAK,CAAC,CAAA;AAAA,IAC9D,eAAA,EAAiBA,EAAE,MAAA,EAAO;AAAA,IAC1B,YAAA,EAAcA,EAAE,MAAA,EAAO;AAAA,IACvB,gBAAgBA,CAAAA,CAAE,IAAA,CAAK,CAAC,SAAA,EAAW,QAAA,EAAU,SAAS,CAAC;AAAA,GACxD,CAAC;AACJ,CAAC,CAAA;AAED,IAAM,kBAAA,GAAqBA,EAAE,MAAA,CAAO;AAAA,EAClC,MAAA,EAAQA,CAAAA,CAAE,IAAA,CAAK,CAAC,SAAA,EAAW,UAAU,OAAA,EAAS,OAAA,EAAS,MAAA,EAAQ,eAAe,CAAC,CAAA;AAAA,EAC/E,kBAAkBA,CAAAA,CAAE,IAAA,CAAK,CAAC,WAAA,EAAa,SAAA,EAAW,aAAa,CAAC,CAAA;AAAA,EAChE,eAAA,EAAiBA,EAAE,IAAA,CAAK,CAAC,WAAW,UAAU,CAAC,EAAE,QAAA,EAAS;AAAA,EAC1D,YAAA,EAAcA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAClC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAChC,gBAAgBA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA,EAAS;AAAA,EAC1C,WAAA,EAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,cAAA,EAAgBA,CAAAA,CAAE,IAAA,CAAK,CAAC,YAAA,EAAc,UAAU,QAAA,EAAU,SAAS,CAAC,CAAA,CAAE,QAAA;AACxE,CAAC,CAAA;AAaM,SAAS,sBAAsB,KAAA,EAAiD;AACrF,EAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,SAAA,CAAU,KAAA,CAAM,KAAK,gBAAgB,CAAA;AACvE,EAAA,OAAO,MAAA,CAAO,OAAA,GAAU,MAAA,CAAO,IAAA,GAAO,MAAA;AACxC;AAeO,SAAS,kBAAkB,KAAA,EAAiD;AACjF,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,SAAA,CAAU,KAAA,CAAM,KAAK,QAAQ,CAAA;AAC3D,EAAA,OAAO,MAAA,CAAO,OAAA,GAAU,MAAA,CAAO,IAAA,GAAO,MAAA;AACxC;AAgBO,SAAS,eAAA,CAAgB,OAAiB,QAAA,EAAgD;AAC/F,EAAA,OAAOa,GAAAA,CAAI;AAAA,IACT,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,OAAA,EAAS,OAAA,CAAQ,wBAAA,EAA0B,EAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,QAAA,CAAS,KAAA,EAAM,EAAG,CAAA;AAAA,IAChF,UAAA,EAAY,QAAQ,2BAA2B,CAAA;AAAA,IAC/C,GAAA,EAAK,EAAE,QAAA;AAAS,GACjB,CAAA;AACH;AC3EA,IAAMC,OAAAA,GAASb,KAAK,MAAA,CAAO,KAAA,CAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,CAAA;AAGvE,SAAS,OAAO,KAAA,EAAyC;AACvD,EAAA,OAAO,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAmC,EAAC;AACpH;AAOA,SAAS,oBAAoB,MAAA,EAA4E;AACvG,EAAA,IAAI,IAAA,GAAO,MAAA;AACX,EAAA,OAAO,CAACE,UAAAA,CAAWK,IAAAA,CAAK,IAAA,EAAM,gBAAgB,CAAC,CAAA,EAAG;AAChD,IAAA,MAAM,MAAA,GAASC,QAAQ,IAAI,CAAA;AAC3B,IAAA,IAAI,MAAA,KAAW,IAAA;AACb,MAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAC3D,IAAA,IAAA,GAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,WAAA,GAAc,SAAS,IAAA,EAAM,MAAM,EAAE,UAAA,CAAW,IAAA,EAAM,GAAG,CAAA,IAAK,GAAA;AACpE,EAAA,MAAM,SAAA,GAAY,kBAAkBL,YAAAA,CAAaI,IAAAA,CAAK,MAAM,gBAAgB,CAAA,EAAG,MAAM,CAAC,CAAA;AACtF,EAAA,IAAI,SAAA,CAAU,IAAA,CAAK,CAAA,QAAA,KAAY,QAAA,CAAS,OAAO,MAAM,CAAA;AACnD,IAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AACzC,EAAA,MAAM,OAAO,SAAA,CAAU,GAAA,CAAI,cAAY,MAAA,CAAO,QAAA,CAAS,MAAM,CAAC,CAAA,CAAE,OAAA,GAAU,IAAA,CAAK,CAAA,QAAA,KAAY,eAAe,MAAA,CAAO,QAAA,CAAS,SAAS,CAAC,CAAA;AACpI,EAAA,IAAI,CAAC,IAAA;AACH,IAAA,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAC/E,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AACvC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA;AACrC,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AACvC,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAC9B,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,EAAY,IAAA,EAA+B,QAAA,KAA4B;AACpF,IAAA,IAAI,OAAA,CAAQ,IAAI,EAAE,CAAA;AAChB,MAAA;AACF,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,MAAM,QAAA,GAAW,QAAA,KAAa,MAAA,GAAY,MAAA,CAAO,QAAA,CAAS,EAAA,CAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAC,CAAC,IAAI,EAAC;AAChF,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA;AAC9C,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,SAAS,KAAK,MAAA,CAAO,OAAA,CAAQ,EAAE,GAAG,MAAA,CAAO,IAAA,CAAK,YAAY,GAAG,GAAG,MAAA,CAAO,KAAK,oBAAoB,CAAA,EAAG,CAAA,EAAG;AACtH,MAAA,IAAI,IAAA,IAAQ,KAAA;AACV,QAAA;AACF,MAAA,MAAM,UAAU,OAAO,SAAA,KAAc,WAAW,SAAA,GAAY,MAAA,CAAO,SAAS,CAAA,CAAE,OAAA;AAC9E,MAAA,IAAI,OAAO,OAAA,KAAY,QAAA;AACrB,QAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AACrD,MAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,OAAO,CAAA,EAAG;AAC/B,QAAA,IAAI,QAAA,KAAa,MAAA;AACf,UAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAChD,QAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,EAAMH,OAAAA,CAAQ,MAAM,QAAA,EAAU,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA,CAAE,UAAA,CAAW,IAAA,EAAM,GAAG,CAAA,IAAK,GAAA;AAClG,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,SAAA,CAAU,MAAM,CAAC,CAAA;AACvC,QAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA;AACvB,UAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AACrD,QAAA,KAAA,CAAM,IAAI,IAAI,CAAA;AACd,QAAA,KAAA,CAAM,CAAA,UAAA,EAAa,MAAM,CAAA,CAAA,EAAI,MAAA,EAAQ,MAAM,CAAA;AAC3C,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,GAAA,GAAM,WAAW,SAAA,IAAa,OAAA,IAAW,WAAW,OAAA,GAAU,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACtF,MAAA,KAAA,CAAM,IAAI,GAAA,CAAI,KAAA,CAAM,yBAAyB,CAAA,GAAI,CAAC,KAAK,IAAI,CAAA;AAC3D,MAAA,MAAM,WAAW,MAAA,CAAO,SAAA,CAAU,GAAG,CAAA,IAAK,QAAA,CAAS,GAAG,CAAC,CAAA;AACvD,MAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,CAAE,UAAU,EAAE,GAAA,IAAO,SAAA,CAAA,IAAc,EAAE,GAAA,IAAO,QAAA,CAAA;AACnE,QAAA,MAAM,IAAI,MAAM,kCAAkC,CAAA;AACpD,MAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,IACrB;AAAA,EACF,CAAA;AACA,EAAA,KAAA,CAAM,CAAA,UAAA,EAAa,WAAW,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,WAAW,CAAC,GAAG,WAAW,CAAA;AAC7E,EAAA,OAAO,EAAE,SAAS,KAAA,EAAO,KAAA,sBAAW,GAAA,CAAI,CAAC,GAAG,KAAA,EAAO,GAAG,MAAA,CAAO,KAAK,MAAA,CAAO,MAAA,CAAO,SAAA,CAAU,WAAW,CAAC,CAAA,CAAE,eAAe,CAAC,CAAC,CAAC,CAAA,EAAG,IAAA,EAAK;AACpI;AAgBA,eAAsB,OAAA,CAAQ,UAAkB,OAAA,EAA6D;AAC3G,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAASA,QAAQ,QAAQ,CAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,oBAAoB,MAAM,CAAA;AAExC,IAAA,MAAM,UAAA,GAAa,wBAAwB,MAAM,CAAA;AACjD,IAAA,MAAM,WAAA,GAAcG,IAAAA,CAAK,UAAA,EAAY,cAAc,CAAA;AACnD,IAAA,MAAM,OAAA,GAAUL,UAAAA,CAAW,WAAW,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,KAAA,CAAMC,YAAAA,CAAa,WAAA,EAAa,MAAM,CAAC,CAAC,IAAI,EAAC;AACnG,IAAA,IAAI,OAAO,OAAA,CAAQ,IAAA,KAAS,YAAY,CAAC,OAAA,CAAQ,KAAK,IAAA,EAAK;AACzD,MAAA,OAAOS,GAAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,4BAA4B,CAAC,CAAA;AAC/E,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAK;AAClC,IAAA,IAAI,CAAC,QAAQ,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA,CAAE,OAAA,CAAQ,eAAe,EAAE,CAAA;AAC7D,MAAA,OAAOA,GAAAA,CAAI,cAAA,CAAe,YAAA,EAAc,OAAA,CAAQ,4BAA4B,CAAC,CAAA;AAC/E,IAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,GAASR,OAAAA,CAAQ,QAAQ,MAAM,CAAA,GAAIF,UAAAA,CAAWK,IAAAA,CAAK,MAAA,EAAQ,MAAM,CAAC,CAAA,GAAI,SAAS,KAAA,CAAM,IAAA;AAC7G,IAAA,MAAM,MAAA,GAAS,yBAAA,CAA0B,EAAE,WAAA,EAAa,OAAA,EAAS,WAAA,IAAe,MAAA,EAAQ,MAAA,EAAQ,WAAA,EAAa,OAAA,EAAS,WAAA,KAAgB,KAAA,CAAA,EAAW,CAAA;AACjJ,IAAA,IAAI,CAAC,MAAA,CAAO,OAAA;AACV,MAAA,OAAO,MAAA;AACT,IAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,MAAA;AACxB,IAAA,MAAM,OAAO,KAAA,CAAM,OAAA;AACnB,IAAA,MAAM,UAAmD,EAAC;AAC1D,IAAA,KAAA,MAAW,CAAC,MAAM,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,EAAE,IAAI,OAAA,EAAS,KAAA,EAAO,SAAS,OAAA,EAAS,SAAA,EAAW,OAAO,OAAA,EAAS,GAAA,EAAK,OAAO,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG;AAC3I,MAAA,OAAA,CAAQ,IAAI,IAAI,EAAC;AACjB,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,CAAA,MAAA,EAAS,KAAK,CAAA,CAAE,CAAA;AAC5B,QAAA;AACF,MAAA,MAAM,aAAa,CAAC,KAAA,EAAO,MAAM,CAAA,CAAE,GAAA,CAAI,SAAOA,IAAAA,CAAK,MAAA,EAAQ,QAAA,EAAU,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,GAAG,EAAE,CAAC,CAAA,CAAE,KAAKL,UAAU,CAAA;AACxG,MAAA,MAAM,SAAS,UAAA,GAAa,oBAAA,CAAqB,IAAA,EAAM,UAAA,EAAY,GAAG,CAAA,GAAI,KAAA,CAAA;AAC1E,MAAA,IAAI,MAAA,IAAU,CAAC,MAAA,CAAO,OAAA;AACpB,QAAA,OAAO,MAAA;AACT,MAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,MAAA,EAAQ,IAAA,IAAQ,EAAC;AAAA,IACnC;AACA,IAAA,MAAM,cAAuC,EAAC;AAC9C,IAAA,MAAM,MAAM,CAAC,OAAA,EAAsB,SAAiB,UAAA,GAAa,OAAA,EAAmB,aAAuB,EAAC,EAAG,MAAA,GAAS,OAAA,CAAQ,UAAU,CAAA,IAAK,IAAI,MAAA,GAAS,CAAA,CAAA,EAAI,UAAU,CAAA,IAAA,CAAA,KAAW;AACnL,MAAA,WAAA,CAAY,IAAA,CAAK,EAAE,OAAA,EAAS,OAAA,EAAS,MAAA,EAAQ,YAAY,UAAA,EAAY,SAAA,EAAW,CAAC,KAAA,EAAO,UAAA,EAAY,GAAG,UAAU,CAAA,CAAE,GAAA,CAAI,CAAA,IAAA,KAAQ,IAAA,CAAK,WAAA,EAAa,EAAE,IAAA,CAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAA;AAAA,IACxK,CAAA;AACA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAChC,IAAA,IAAI,IAAA,CAAK,IAAI,aAAa,CAAA;AACxB,MAAA,GAAA,CAAI,IAAA,EAAM,MAAA,CAAO,OAAA,CAAQ,EAAA,CAAG,IAAA,IAAQ,QAAQ,CAAA,EAAG,IAAA,EAAM,EAAC,EAAG,OAAA,CAAQ,EAAA,EAAI,uBAAuB,CAAA;AAC9F,IAAA,IAAI,IAAA,CAAK,IAAI,aAAa,CAAA;AACxB,MAAA,GAAA,CAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,IAAA,IAAQ,QAAQ,CAAA,EAAG,OAAA,EAAS,EAAC,EAAG,OAAA,CAAQ,KAAA,EAAO,0BAA0B,CAAA;AAC7G,IAAA,IAAI,IAAA,CAAK,IAAI,eAAe,CAAA;AAC1B,MAAA,GAAA,CAAI,WAAW,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,IAAQ,OAAO,CAAC,CAAA;AACxD,IAAA,IAAI,IAAA,CAAK,IAAI,aAAa,CAAA;AACxB,MAAA,GAAA,CAAI,SAAS,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,IAAA,IAAQ,SAAS,CAAC,CAAA;AACtD,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AACpC,MAAA,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,CAAE,IAAA,KAAS,IAAA,GAAO,MAAA,GAAS,YAAY,KAAA,EAAO,CAAC,MAAM,CAAA,EAAG,MAAM,kBAAkB,CAAA;AAAA,IACtH;AACA,IAAA,MAAM,SAAA,GAAY,QAAQ,KAAA,CAAM,SAAA;AAChC,IAAA,IAAI,KAAK,GAAA,CAAI,aAAa,KAAK,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvD,MAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,CAAA,IAAK,SAAA,CAAU,SAAQ,EAAG;AAC/C,QAAA,MAAM,QAAA,GAAW,OAAO,IAAI,CAAA;AAC5B,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,QAAA,CAAS,IAAA,IAAQ,EAAE,CAAA;AAEvC,QAAA,MAAM,OAAA,GAAU,SAAS,YAAA,IAAiB,CAAC,WAAW,KAAK,CAAA,CAAE,QAAA,CAAS,IAAI,CAAA,IAAK,QAAA,CAAS,SAAS,KAAA,GAAS,KAAA,GAAQ,CAAC,MAAA,EAAQ,KAAA,EAAO,SAAS,CAAA,CAAE,QAAA,CAAS,IAAI,CAAA,GAAI,OAAA,GAAU,KAAA,CAAA;AACxK,QAAA,IAAI,OAAA;AACF,UAAA,GAAA,CAAI,OAAA,EAAS,IAAA,EAAM,OAAA,EAAS,CAAC,WAAA,EAAa,OAAO,KAAK,CAAC,CAAA,EAAG,QAAA,EAAU,aAAa,CAAA;AAAA,MACrF;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,aAAa,CAAA,IAAK,CAAC,YAAY,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAA,CAAK,UAAA,KAAe,OAAO,CAAA;AAClF,MAAA,GAAA,CAAI,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,CAAC,WAAA,EAAa,GAAG,CAAA,EAAG,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,IAAa,aAAa,CAAA;AACxG,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,eAAe,CAAA;AACnD,IAAA,MAAM,IAAA,GAAmB;AAAA,MACvB,MAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA,EAAY,CAAC,GAAG,IAAI,CAAA,CAAE,MAAA,CAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,MACrE,OAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA,EAAkB,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,0BAA0B,CAAA;AAAA,MAC5D,oBAAA,EAAsB,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,wBAAwB,CAAA;AAAA,MAC9D,gBAAA,EAAkB,CAAC,GAAG,IAAI,GAAA,CAAI,WAAA,CAAY,GAAA,CAAI,CAAA,IAAA,KAAQ,IAAA,CAAK,OAAO,CAAC,CAAC,CAAA;AAAA,MACpE,eAAA,EAAiB,MAAA,CAAO,WAAA,CAAY,WAAA,CAAY,GAAA,CAAI,CAAA,IAAA,KAAQ,CAAC,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,OAAO,CAAC,CAAC;AAAA,KAC3F;AACA,IAAAW,QAAO,IAAA,CAAK,qBAAA,EAAuB,EAAE,OAAA,EAAS,KAAK,OAAA,EAAS,UAAA,EAAY,IAAA,CAAK,UAAA,EAAY,kBAAkB,IAAA,CAAK,gBAAA,EAAkB,eAAA,EAAiB,IAAA,CAAK,iBAAiB,CAAA;AACzK,IAAA,OAAOF,GAAG,IAAI,CAAA;AAAA,EAChB,CAAA,CAAA,MACM;AAEJ,IAAA,OAAOC,GAAAA,CAAI,cAAA,CAAe,WAAA,EAAa,OAAA,CAAQ,mBAAA,EAAqB,EAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,iHAAA,EAAkH,EAAG,CAAC,CAAA;AAAA,EAC/M;AACF;;;ACnKO,SAAS,kCAAA,GAA6C;AAC3D,EAAA,MAAM,WAAA,GAAc,CAAC,4BAAA,EAA8B,4BAAA,EAA8B,6BAA6B,2BAA2B,CAAA,CACtI,GAAA,CAAI,CAAA,GAAA,KAAO,CAAA,yBAAA,EAA4B,GAAG,CAAA,IAAA,CAAM,CAAA,CAChD,KAAK,GAAG,CAAA;AACX,EAAA,OAAO,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wDAAA,EAiB0C,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAcrE;AC1CA,IAAM,MAAA,GAAS;AAAA,EACb,EAAE,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,CAAC,mBAAA,EAAqB,gBAAA,EAAkB,qBAAqB,CAAA,EAAG,QAAA,EAAU,CAAC,IAAA,EAAM,OAAO,CAAA,EAAE;AAAA,EACvH,EAAE,IAAA,EAAM,kBAAA,EAAoB,IAAA,EAAM,CAAC,mBAAA,EAAqB,qBAAqB,CAAA,EAAG,QAAA,EAAU,CAAC,SAAS,CAAA,EAAE;AAAA,EACtG,EAAE,IAAA,EAAM,eAAA,EAAiB,IAAA,EAAM,CAAC,qBAAqB,CAAA,EAAG,QAAA,EAAU,CAAC,MAAM,CAAA;AAC3E,CAAA;AACA,IAAM,WAAA,GAAsC,EAAE,EAAA,EAAI,QAAA,EAAU,OAAO,WAAA,EAAa,OAAA,EAAS,aAAA,EAAe,IAAA,EAAM,cAAA,EAAe;AActH,SAAS,0BAAA,CAA2B,WAAA,EAAqB,MAAA,EAAiB,YAAA,GAAwC,EAAC,EAAa;AACrI,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA;AACvB,IAAA,OAAO,EAAC;AACV,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA;AACnB,MAAA;AACF,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AACjC,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,YAAA,EAAc,MAAM,CAAA;AACrC,MAAA;AACF,IAAA,MAAM,WAAA,GAAc,aAAa,MAAM,CAAA;AACvC,IAAA,MAAM,UAAU,WAAA,IAAe,OAAO,WAAA,KAAgB,QAAA,GAAW,cAAc,EAAC;AAChF,IAAA,MAAM,SAAS,MAAA,IAAU,OAAA,IAAW,OAAO,OAAA,CAAQ,IAAA,KAAS,WACxD,OAAA,CAAQ,IAAA,GACR,UAAA,IAAc,OAAA,IAAW,QAAQ,QAAA,KAAa,IAAA,GAAO,SAAS,CAAA,IAAA,EAAO,WAAW,IAAI,MAAM,CAAA,CAAA;AAC9F,IAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,MAAM,CAAA;AAC5B,MAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,8BAA8B,CAAC,CAAA;AACzD,IAAA,OAAA,CAAQ,IAAI,MAAM,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,CAAC,GAAG,OAAO,CAAA;AACpB;AAiBO,SAAS,yBAAA,CAA0B,WAAA,EAAqB,iBAAA,EAA2B,OAAA,EAG/D;AACzB,EAAA,MAAM,MAAA,GAASE,SAAS,iBAAiB,CAAA;AACzC,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,MAAA,GAAS,CAAC,GAAG,IAAI,IAAI,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA,GAAA,KAAO,MAAA,CAAO,GAAG,CAAA,KAAM,MAAA,GAAY,EAAC,GAAI,CAAC,OAAO,GAAG,CAAE,CAAC,CAAC,CAAC,CAAA;AACtG,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA;AACV,MAAA;AACF,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,IAAK,CAAC,cAAc,IAAA,CAAK,MAAA,CAAO,CAAC,CAAE,CAAA;AACvD,MAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,8BAA8B,CAAC,CAAA;AACzD,IAAA,UAAA,CAAW,IAAA,CAAK,GAAG,KAAA,CAAM,IAAI,IAAI,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAC5C,IAAA,KAAA,MAAW,GAAA,IAAO,MAAM,IAAA,CAAK,MAAA,CAAO,CAAAC,IAAAA,KAAO,MAAA,CAAOA,IAAG,CAAA,KAAM,MAAS,CAAA;AAClE,MAAA,QAAA,CAAS,IAAI,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,MAAA,CAAQ,CAAA;AAC3C,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,QAAA,EAAU;AACjC,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA;AACrC,MAAA,IAAI,CAAC,OAAA,EAAS,QAAA;AACZ,QAAA;AACF,MAAA,QAAA,CAAS,GAAA,CAAI,GAAG,KAAA,CAAM,IAAI,IAAI,WAAA,CAAY,IAAI,CAAC,CAAA,OAAA,CAAS,CAAA;AACxD,MAAA,KAAA,MAAW,UAAU,0BAAA,CAA2B,WAAA,EAAa,OAAA,CAAQ,OAAA,EAAS,QAAQ,OAAO,CAAA;AAC3F,QAAA,OAAA,CAAQ,IAAI,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,CAAA;AAAA,IACzC;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,iBAAA,EAAmB,OAAO,WAAW;AAAA,CAAA;AAAA,IACrC,0BAA0B,UAAA,CAAW,MAAA,GAAS,GAAG,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA,GAAO,EAAA;AAAA,IAC7E,kBAAA,EAAoB,QAAA,CAAS,IAAA,GAAO,CAAA,EAAG,CAAC,GAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA,GAAO,EAAA;AAAA,IACtE,iBAAA,EAAmB,OAAA,CAAQ,IAAA,GAAO,CAAA,EAAG,CAAC,GAAG,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA,GAAO,EAAA;AAAA,IACnE,8BAA8B,yBAAA;AAA0B,GAC1D;AACF;AAaO,SAAS,mCAAA,GAA8C;AAC5D,EAAA,OAAO,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAqBhB;AAGA,SAAS,yBAAA,GAAoC;AAC3C,EAAA,OAAO,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAuHd,OAAA,CAAQ,8BAAA,EAAgC,mCAAA,EAAqC,CAAA;AAC/E;;;ACvPA,IAAM,eAAA,GAAqD;AAAA,EACzD,EAAA,EAAI,CAAC,YAAA,EAAc,OAAO,CAAA;AAAA,EAC1B,OAAA,EAAS,CAAC,QAAA,EAAU,OAAO,CAAA;AAAA,EAC3B,KAAA,EAAO,CAAC,QAAA,EAAU,UAAA,EAAY,QAAQ;AACxC,CAAA;AAgBO,SAAS,wBAAA,CAAyB,WAAA,EAAqB,OAAA,EAG3D,QAAA,EAAqD;AACtD,EAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,WAAW,CAAA;AAC/B,IAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,wBAAwB,CAAC,CAAA;AACnD,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,KAAA,MAAW,eAAe,QAAA,EAAU;AAClC,IAAA,MAAM,QAAA,GAAW,gBAAgB,WAAW,CAAA;AAC5C,IAAA,IAAI,CAAC,QAAA;AACH,MAAA;AACF,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA;AAC5C,IAAA,MAAM,QAAQ,OAAA,EAAS,KAAA;AACvB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA;AACnB,MAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,wBAAwB,CAAC,CAAA;AACnD,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,WAAA,CAAY,GAAG,CAAA,GAAI,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AACxE,IAAA,MAAM,MAAA,GAAS,WAAA,KAAgB,UAAA,GAAa,YAAA,GAAe,WAAA;AAC3D,IAAA,MAAM,eAAe,0BAAA,CAA2B,WAAA,EAAa,OAAA,CAAQ,OAAA,EAAS,QAAQ,OAAO,CAAA;AAC7F,IAAA,IAAI,CAAC,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,IAAK,YAAA,CAAa,MAAA,KAAW,CAAA,IAAK,OAAA,CAAQ,GAAA,CAAI,YAAA,CAAa,CAAC,CAAE,CAAA;AACzF,MAAA,MAAM,IAAI,KAAA,CAAM,OAAA,CAAQ,wBAAwB,CAAC,CAAA;AACnD,IAAA,MAAM,MAAA,GAAS,aAAa,CAAC,CAAA;AAC7B,IAAA,OAAA,CAAQ,IAAI,MAAM,CAAA;AAClB,IAAA,MAAA,CAAO,KAAK,CAAA,EAAG,WAAW,IAAI,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,CAAA;AAAA,EAClD;AACA,EAAA,OAAO;AAAA,IACL,kBAAkB,MAAA,CAAO,MAAA,GAAS,GAAG,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA,GAAO,EAAA;AAAA,IAC7D,0BAAA,EAA4B,wBAAA,EAAyB,CAClD,OAAA,CAAQ,eAAe,WAAW,CAAA,CAClC,OAAA,CAAQ,8BAAA,EAAgC,qCAAqC,CAAA,CAC7E,OAAA,CAAQ,8BAAA,EAAgC,oCAAoC;AAAA,GACjF;AACF;AAGA,SAAS,wBAAA,GAAmC;AAC1C,EAAA,OAAO,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAqOhB;AC5RA,IAAM,YAAY,MAAA,CAAO,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA+HzB,SAAS,WAAW,MAAA,EAA0B;AAC5C,EAAA,OAAO,CAAC,SAAA,EAAW,YAAA,EAAc,iBAAA,EAAmB,iBAAA,EAAmB,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,SAAS,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAC,CAAA;AAC1H;AAeO,SAAS,cAAA,CAAe,SAAiB,IAAA,EAA+E;AAC7H,EAAA,MAAM,IAAA,GAAO,CAAA,kBAAA,EAAqB,UAAA,EAAY,CAAA,CAAA;AAC9C,EAAA,MAAM,MAAM,CAAA,iBAAA,EAAoB,UAAA,GAAa,UAAA,CAAW,GAAA,EAAK,EAAE,CAAC,CAAA,CAAA;AAChE,EAAA,MAAM,MAAA,GAAS,CAAA;AAAA;AAAA;AAAA,EAGf,SAAS;AAAA;AAAA,wDAAA,EAE+C,GAAG,CAAA;AAAA,yCAAA,EAClB,GAAG,CAAA;AAAA;AAAA,8EAAA,CAAA;AAG5C,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,WAAW,MAAM,CAAA,EAAG,KAAK,EAAE,CAAC,GAAG,GAAG,IAAA,CAAK,UAAU,EAAE,IAAA,EAAM,SAAS,IAAA,EAAM,GAAE,EAAE;AACnG;AAcO,SAAS,gBAAgB,IAAA,EAAwB;AACtD,EAAA,OAAO,UAAA,CAAW,CAAA;AAAA;AAAA;AAAA,EAGlB,SAAS;AAAA;AAAA,8BAAA,EAEqB,IAAI,CAAA;AAAA,kBAAA,CACjB,CAAA;AACnB;;;AChLA,eAAe,YAAY,GAAA,EAA+B;AACxD,EAAA,IAAI;AACF,IAAAV,QAAAA,CAAQ,IAAA,CAAK,CAAC,GAAA,EAAK,CAAC,CAAA;AAAA,EACtB,SACO,KAAA,EAAO;AACZ,IAAA,OAAO,KAAA,YAAiB,KAAA,IAAS,MAAA,IAAU,KAAA,IAAS,MAAM,IAAA,KAAS,OAAA;AAAA,EACrE;AACA,EAAA,IAAIA,SAAQ,QAAA,KAAa,OAAA;AACvB,IAAA,OAAO,KAAA;AACT,EAAA,IAAI;AACF,IAAA,KAAA,MAAW,KAAA,IAAS,MAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1C,MAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AACrB,QAAA;AACF,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACF,QAAA,IAAA,GAAO,MAAM,QAAA,CAAS,CAAA,MAAA,EAAS,KAAK,SAAS,MAAM,CAAA;AAAA,MACrD,SACO,KAAA,EAAO;AACZ,QAAA,IAAI,KAAA,YAAiB,KAAA,IAAS,MAAA,IAAU,KAAA,IAAS,MAAM,IAAA,KAAS,QAAA;AAC9D,UAAA;AACF,QAAA,OAAO,KAAA;AAAA,MACT;AAEA,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,GAAG,CAAA,GAAI,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA;AAC9D,MAAA,IAAI,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA,KAAM,GAAA,IAAO,MAAA,CAAO,CAAC,CAAA,KAAM,GAAA,IAAO,MAAA,CAAO,CAAC,CAAA,KAAM,GAAA;AAClE,QAAA,OAAO,KAAA;AAAA,IACX;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MACM;AACJ,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAGA,eAAe,MAAA,CAAO,OAAA,EAAiB,IAAA,EAAgB,SAAA,EAAqC;AAC1F,EAAA,IAAI,SAAA,IAAa,CAAA;AACf,IAAA,OAAO,KAAA;AACT,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACD,QAAAA,KAAY;AAC9B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM,EAAE,WAAA,EAAa,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,CAAA;AACvF,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI,KAAA;AACJ,IAAA,MAAM,MAAA,GAAS,CAAC,OAAA,KAA2B;AACzC,MAAA,IAAI,OAAA;AACF,QAAA;AACF,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,IAAI,KAAA;AACF,QAAA,YAAA,CAAa,KAAK,CAAA;AACpB,MAAAA,SAAQ,OAAO,CAAA;AAAA,IACjB,CAAA;AACA,IAAA,KAAA,GAAQ,UAAA,CAAW,WAAW,MAAM;AAClC,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAA,EAAM;AACZ,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACd,GAAG,SAAS,CAAA;AACZ,IAAA,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,MAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACvC,IAAA,KAAA,CAAM,KAAK,OAAA,EAAS,CAAA,IAAA,KAAQ,MAAA,CAAO,IAAA,KAAS,CAAC,CAAC,CAAA;AAAA,EAChD,CAAC,CAAA;AACH;AAsCO,SAAS,YAAA,CAAa,OAAA,EAAiB,IAAA,EAAgB,OAAA,EAAwE;AACpI,EAAA,MAAM,MAAMC,QAAAA,CAAQ,QAAA,KAAa,UAAU,cAAA,CAAe,OAAA,EAAS,IAAI,CAAA,GAAI,MAAA;AAC3E,EAAA,MAAM,QAAQ,KAAA,CAAM,GAAA,GAAM,mBAAmB,OAAA,EAAS,GAAA,EAAK,QAAQ,IAAA,EAAM;AAAA,IACvE,GAAG,OAAA;AAAA,IACH,GAAA,EAAK,GAAA,GAAM,EAAE,GAAG,OAAA,CAAQ,KAAK,GAAG,GAAA,CAAI,GAAA,EAAI,GAAI,OAAA,CAAQ,GAAA;AAAA,IACpD,WAAA,EAAa,IAAA;AAAA,IACb,KAAA,EAAO,KAAA;AAAA,IACP,UAAU,CAAC;AAAA,GACZ,CAAA;AACD,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,CAAM,IAAA,CAAK,QAAQ,MAAM;AACvB,IAAA,MAAA,GAAS,IAAA;AAAA,EACX,CAAC,CAAA;AACD,EAAA,KAAA,CAAM,IAAA,CAAK,SAAS,MAAM;AACxB,IAAA,MAAA,GAAS,IAAA;AAAA,EACX,CAAC,CAAA;AACD,EAAA,IAAI,WAAA;AACJ,EAAA,MAAM,aAAa,YAA8B;AAC/C,IAAA,IAAI,CAAC,KAAA,CAAM,GAAA;AACT,MAAA,OAAO,IAAA;AACT,IAAA,IAAI,GAAA;AACF,MAAA,OAAO,UAAU,MAAA,CAAO,gBAAA,EAAkB,gBAAgB,GAAA,CAAI,IAAI,GAAG,GAAI,CAAA;AAC3E,IAAA,OAAO,WAAA,CAAY,MAAM,GAAG,CAAA;AAAA,EAC9B,CAAA;AACA,EAAA,MAAM,SAAA,GAAY,CAAC,SAAA,KAAwD;AACzE,IAAA,WAAA,KAAA,CAAiB,YAAY;AAC3B,MAAA,MAAM,QAAA,GAAW,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AACrC,MAAA,IAAI,oBAAA,GAAuB,CAAC,GAAA,IAAO,MAAA;AACnC,MAAA,IAAI,MAAM,GAAA,EAAK;AACb,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,IAAI,CAAC,MAAA,EAAQ;AAEX,YAAA,oBAAA,GAAuB,MAAM,MAAA,CAAO,UAAA,EAAY,CAAC,MAAA,EAAQ,MAAA,CAAO,MAAM,GAAG,CAAA,EAAG,MAAM,IAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,WAAW,WAAA,CAAY,GAAA,EAAK,CAAC,CAAA;AAClI,YAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,UACtB;AAAA,QACF,CAAA,MACK;AACH,UAAA,IAAI;AACF,YAAAA,QAAAA,CAAQ,IAAA,CAAK,CAAC,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,UACpC,CAAA,CAAA,MACM;AAAA,UAEN;AAAA,QACF;AAAA,MACF;AACA,MAAA,OAAO,WAAA,CAAY,GAAA,EAAI,GAAI,QAAA,EAAU;AACnC,QAAA,IAAI,MAAA;AACF,UAAA;AACF,QAAA,MAAMW,aAAW,EAAE,CAAA;AAAA,MACrB;AACA,MAAA,IAAI,QAAA,GAAW,KAAA;AACf,MAAA,IAAI,UAAU,GAAA,EAAK;AAEjB,QAAA,QAAA,GAAW,MAAM,MAAA,CAAO,gBAAA,EAAkB,eAAA,CAAgB,GAAA,CAAI,IAAI,CAAA,EAAG,QAAA,GAAW,WAAA,CAAY,GAAA,EAAK,CAAA;AACjG,QAAA,QAAA,KAAa,oBAAA,IAAwB,MAAM,QAAA,KAAa,IAAA;AAAA,MAC1D,WACS,MAAA,EAAQ;AACf,QAAA,OAAO,WAAA,CAAY,GAAA,EAAI,GAAI,QAAA,EAAU;AACnC,UAAA,IAAI,MAAM,YAAW,EAAG;AACtB,YAAA,QAAA,GAAW,IAAA;AACX,YAAA;AAAA,UACF;AACA,UAAA,MAAMA,aAAW,EAAE,CAAA;AAAA,QACrB;AAAA,MACF;AAGA,MAAA,KAAA,CAAM,MAAM,OAAA,EAAQ;AACpB,MAAA,KAAA,CAAM,OAAO,OAAA,EAAQ;AACrB,MAAA,KAAA,CAAM,OAAO,OAAA,EAAQ;AACrB,MAAA,IAAI,CAAC,QAAA;AACH,QAAA,KAAA,CAAM,KAAA,EAAM;AACd,MAAA,OAAO,WAAW,WAAA,GAAc,SAAA;AAAA,IAClC,CAAA,GAAG;AACH,IAAA,OAAO,WAAA;AAAA,EACT,CAAA;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,UAAA,EAAY,SAAA,EAAU;AACxC;;;ACzJO,SAAS,kBAAA,CAAmB,OAAA,GAA6B,EAAC,EAAiB;AAChF,EAAA,MAAM,SAAS,CAAC,GAAG,IAAI,GAAA,CAAI,OAAA,CAAQ,OAAO,OAAO,CAAC,CAAC,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,GAAS,EAAE,MAAM,CAAA;AACvF,EAAA,IAAI,MAAA,CAAO,OAAO,CAAC,KAAA,EAAO,UAAU,KAAA,GAAQ,KAAA,CAAM,MAAA,EAAQ,CAAC,CAAA,GAAI,OAAA;AAC7D,IAAA,MAAM,IAAI,WAAW,qCAAqC,CAAA;AAC5D,EAAA,MAAM,UAAU,MAAA,CAAO,MAAA,GAAS,IAAI,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA,KAAA,KAAS,KAAA,CAAM,OAAA,CAAQ,qBAAA,EAAuB,MAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA,EAAG,GAAG,CAAA,GAAI,MAAA;AAC/H,EAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAA,CAAI,OAAO,CAAC,CAAA,EAAG,MAAA,IAAU,CAAA,IAAK,CAAC,CAAA;AAC3D,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,IAAI,KAAA,GAAQ,KAAA;AAGZ,EAAA,SAAS,MAAM,KAAA,EAAwB;AACrC,IAAA,IAAI,GAAA,GAAM,QAAQ,OAAA,CAAQ,MAAA,GAAS,KAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,MAAA,GAAS,UAAU,CAAA;AAE1E,IAAA,IAAI,MAAM,CAAA,IAAK,GAAA,GAAM,OAAA,CAAQ,MAAA,IAAU,kBAAkB,IAAA,CAAK,OAAA,CAAQ,GAAA,GAAM,CAAC,CAAE,CAAA,IAAK,iBAAA,CAAkB,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAE,CAAA;AACtH,MAAA,GAAA,EAAA;AACF,IAAA,IAAI,GAAA,KAAQ,CAAA;AACV,MAAA,OAAO,EAAA;AACT,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,OAAA,CAAQ,SAAA,GAAY,CAAA;AACpB,MAAA,IAAI,KAAA,GAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAChC,MAAA,OAAO,KAAA,IAAS,KAAA,CAAM,KAAA,GAAQ,GAAA,EAAK;AACjC,QAAA,MAAA,IAAU,GAAG,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,KAAA,CAAM,KAAK,CAAC,CAAA,GAAA,CAAA;AAC/C,QAAA,MAAA,GAAS,OAAA,CAAQ,SAAA;AAEjB,QAAA,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,MAAM,CAAA;AAC1B,QAAA,KAAA,GAAQ,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,MAC9B;AAAA,IACF;AACA,IAAA,MAAA,IAAU,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,GAAG,CAAA;AACnC,IAAA,OAAA,GAAU,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC3B,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,EAAM;AACV,MAAA,IAAI,KAAA;AACF,QAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAC3C,MAAA,OAAA,IAAW,IAAA;AACX,MAAA,OAAO,MAAM,KAAK,CAAA;AAAA,IACpB,CAAA;AAAA,IACA,GAAA,GAAM;AACJ,MAAA,IAAI,KAAA;AACF,QAAA,OAAO,EAAA;AACT,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,OAAO,MAAM,IAAI,CAAA;AAAA,IACnB;AAAA,GACF;AACF;;;AChEA,IAAMH,OAAAA,GAASb,KAAK,MAAA,CAAO,KAAA,CAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,CAAA;AAgEhE,SAAS,WAAA,CAAY,IAAA,EAAc,OAAA,GAAoB,EAAC,EAAW;AACxE,EAAA,MAAM,MAAA,GAAS,mBAAmB,OAAO,CAAA;AACzC,EAAA,OAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,GAAI,OAAO,GAAA,EAAI;AACzC;AAsBA,eAAsB,UAAA,CAAW,OAAA,EAAiB,IAAA,EAAgB,OAAA,GAA0B,EAAC,EAAsC;AAEjI,EAAA,MAAM,OAAA,GAAU,CAAC,OAAA,EAAiB,KAAA,KAAgDY,GAAAA,CAAI;AAAA,IACpF,GAAG,cAAA,CAAe,qBAAA;AAAA,IAClB,OAAA,EAAS,GAAG,OAAO;AAAA,EAAK,OAAA,CAAQ,KAAA,CAAM,gBAAA,KAAqB,WAAA,GAAc,qBAAA,GAAwB,MAAM,gBAAA,KAAqB,aAAA,GAAgB,wBAAA,GAA2B,qBAAqB,CAAC,CAAA,CAAA;AAAA,IAC7L,GAAA,EAAK,EAAE,gBAAA,EAAkB,KAAA;AAAM,GAChC,CAAA;AACD,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,IAAI,OAAA,CAAQ,CAACR,QAAAA,KAAY;AACpC,MAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,CAAC,OAAA,IAAW,OAAA,CAAQ,SAAS,IAAI,CAAA,IAAK,IAAA,CAAK,IAAA,CAAK,cAAY,OAAO,QAAA,KAAa,YAAY,QAAA,CAAS,QAAA,CAAS,IAAI,CAAC,CAAA;AACpJ,QAAA,MAAM,IAAI,UAAU,2BAA2B,CAAA;AACjD,MAAA,IAAI,OAAA,CAAQ,KAAA,KAAU,KAAA,CAAA,IAAa,OAAO,QAAQ,KAAA,KAAU,QAAA;AAC1D,QAAA,MAAM,IAAI,UAAU,uBAAuB,CAAA;AAC7C,MAAA,MAAM,UAAA,GAAa,QAAQ,eAAA,IAAmB,OAAA;AAC9C,MAAA,IAAI,CAAC,MAAA,CAAO,aAAA,CAAc,UAAU,CAAA,IAAK,UAAA,IAAc,KAAK,UAAA,GAAa,QAAA;AACvE,QAAA,MAAM,IAAI,WAAW,+BAA+B,CAAA;AACtD,MAAA,MAAM,kBAAA,GAAqB,QAAQ,oBAAA,IAAwB,GAAA;AAC3D,MAAA,IAAI,CAAC,MAAA,CAAO,aAAA,CAAc,kBAAkB,CAAA,IAAK,kBAAA,IAAsB,KAAK,kBAAA,GAAqB,GAAA;AAC/F,QAAA,MAAM,IAAI,WAAW,qCAAqC,CAAA;AAC5D,MAAA,IAAI,OAAA,CAAQ,SAAA,KAAc,KAAA,CAAA,KAAc,CAAC,MAAA,CAAO,aAAA,CAAc,OAAA,CAAQ,SAAS,CAAA,IAAK,OAAA,CAAQ,SAAA,IAAa,CAAA,IAAK,QAAQ,SAAA,GAAY,UAAA,CAAA;AAChI,QAAA,MAAM,IAAI,WAAW,yBAAyB,CAAA;AAChD,MAAA,MAAM,UAAU,CAAC,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAG,CAAA;AAC3C,MAAA,MAAM,WAAA,GAAc,WAAA,CAAY,OAAA,EAAS,OAAO,CAAA;AAChD,MAAA,MAAM,YAAA,GAAe,mBAAmB,OAAO,CAAA;AAC/C,MAAA,MAAM,WAAA,GAAc,mBAAmB,OAAO,CAAA;AAC9C,MAAA,MAAM,OAAA,GAAU,aAAa,OAAA,EAAS,IAAA,EAAM,EAAE,GAAA,EAAK,OAAA,CAAQ,KAAK,GAAA,EAAK,OAAA,CAAQ,MAAM,EAAE,GAAGC,SAAQ,GAAA,EAAK,GAAG,QAAQ,GAAA,EAAI,GAAIA,QAAAA,CAAQ,GAAA,EAAK,CAAA;AACrI,MAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA;AACtB,MAAA,KAAA,CAAM,MAAA,CAAO,YAAY,MAAM,CAAA;AAC/B,MAAA,KAAA,CAAM,MAAA,CAAO,YAAY,MAAM,CAAA;AAC/B,MAAA,IAAI,MAAA,GAAS,EAAA;AACb,MAAA,IAAI,MAAA,GAAS,EAAA;AACb,MAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,MAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,IAAI,WAAA,GAAc,KAAA;AAClB,MAAA,IAAI,YAAA;AACJ,MAAA,IAAI,KAAA;AACJ,MAAA,MAAM,MAAA,GAAS,CAAC,MAAA,KAA2C;AACzD,QAAA,IAAI,OAAA;AACF,UAAA;AACF,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,IAAI,KAAA;AACF,UAAA,YAAA,CAAa,KAAK,CAAA;AACpB,QAAAD,SAAQ,MAAM,CAAA;AAAA,MAChB,CAAA;AAEA,MAAA,MAAM,SAAA,GAAY,CAAC,MAAA,EAAsC,OAAA,KAAmC;AAC1F,QAAA,WAAA,GAAc,IAAA;AACd,QAAA,YAAA,KAAA,CAAkB,YAAY;AAC5B,UAAA,IAAI,KAAA;AACF,YAAA,YAAA,CAAa,KAAK,CAAA;AACpB,UAAA,MAAM,mBAAmB,KAAA,CAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,SAAA,CAAU,kBAAkB,CAAA,GAAI,aAAA;AACnF,UAAAS,OAAAA,CAAO,MAAM,6BAAA,EAA+B,EAAE,SAAS,WAAA,EAAa,MAAA,EAAQ,kBAAkB,CAAA;AAC9F,UAAA,MAAA,CAAO,QAAQ,OAAA,EAAS,EAAE,MAAA,EAAQ,gBAAA,EAAkB,CAAC,CAAA;AAAA,QACvD,CAAA,GAAG;AACH,QAAA,OAAO,YAAA;AAAA,MACT,CAAA;AAEA,MAAA,MAAM,OAAA,GAAU,OAAO,IAAA,KAAgC;AACrD,QAAA,IAAI,CAAC,QAAQ,OAAA,IAAW,WAAA;AACtB,UAAA;AACF,QAAA,eAAA,KAAoB,MAAA,CAAO,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS,UAAA;AAClD,QAAA,MAAA,GAAA,CAAU,MAAA,GAAS,IAAA,EAAM,KAAA,CAAM,CAAC,UAAU,CAAA;AAC1C,QAAA,IAAI;AACF,UAAA,MAAM,OAAA,CAAQ,WAAW,IAAI,CAAA;AAAA,QAC/B,CAAA,CAAA,MACM;AACJ,UAAA,MAAM,SAAA,CAAU,QAAA,EAAU,OAAA,CAAQ,sBAAA,EAAwB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,OAAO,OAAA,CAAQ,4BAA4B,CAAA,EAAE,EAAG,CAAC,CAAA;AAAA,QAC/I;AAAA,MACF,CAAA;AACA,MAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAuB;AAC3C,QAAA,eAAA,KAAoB,MAAA,CAAO,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS,UAAA;AAClD,QAAA,MAAA,GAAA,CAAU,MAAA,GAAS,IAAA,EAAM,KAAA,CAAM,CAAC,UAAU,CAAA;AAAA,MAC5C,CAAA;AACA,MAAA,IAAI,OAAA,CAAQ,SAAA,IAAa,OAAA,CAAQ,SAAA,GAAY,CAAA,EAAG;AAC9C,QAAA,KAAA,GAAQ,WAAW,MAAM;AACvB,UAAAA,OAAAA,CAAO,MAAM,mBAAA,EAAqB,EAAE,SAAS,WAAA,EAAa,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAW,CAAA;AAExF,UAAA,KAAK,SAAA,CAAU,SAAA,EAAW,OAAA,CAAQ,uBAAA,EAAyB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAY,EAAG,CAAC,CAAA;AAAA,QAClG,CAAA,EAAG,QAAQ,SAAS,CAAA;AAAA,MACtB;AAEA,MAAA,MAAM,cAAc,YAAY;AAC9B,QAAA,IAAI;AACF,UAAA,WAAA,MAAiB,KAAA,IAAS,MAAM,MAAA,EAAkC;AAChE,YAAA,IAAI,OAAA,IAAW,WAAA;AACb,cAAA;AACF,YAAA,IAAI,OAAO,KAAA,KAAU,QAAA;AACnB,cAAA,MAAM,IAAI,UAAU,sCAAsC,CAAA;AAC5D,YAAA,MAAM,OAAA,CAAQ,YAAA,CAAa,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,UACzC;AACA,UAAA,IAAI,CAAC,WAAW,CAAC,WAAA;AACf,YAAA,MAAM,OAAA,CAAQ,YAAA,CAAa,GAAA,EAAK,CAAA;AAAA,QACpC,CAAA,CAAA,MACM;AACJ,UAAA,MAAM,SAAA,CAAU,QAAA,EAAU,OAAA,CAAQ,sBAAA,EAAwB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,OAAO,OAAA,CAAQ,4BAA4B,CAAA,EAAE,EAAG,CAAC,CAAA;AAAA,QAC/I;AAAA,MACF,CAAA,GAAG;AACH,MAAA,MAAM,aAAa,YAAY;AAC7B,QAAA,IAAI;AACF,UAAA,WAAA,MAAiB,KAAA,IAAS,MAAM,MAAA,EAAkC;AAChE,YAAA,IAAI,OAAA,IAAW,WAAA;AACb,cAAA;AACF,YAAA,IAAI,OAAO,KAAA,KAAU,QAAA;AACnB,cAAA,MAAM,IAAI,UAAU,4CAA4C,CAAA;AAClE,YAAA,YAAA,CAAa,WAAA,CAAY,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,UACvC;AACA,UAAA,IAAI,CAAC,WAAW,CAAC,WAAA;AACf,YAAA,YAAA,CAAa,WAAA,CAAY,KAAK,CAAA;AAAA,QAClC,CAAA,CAAA,MACM;AACJ,UAAA,MAAM,SAAA,CAAU,QAAA,EAAU,OAAA,CAAQ,sBAAA,EAAwB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,OAAO,OAAA,CAAQ,4BAA4B,CAAA,EAAE,EAAG,CAAC,CAAA;AAAA,QAC/I;AAAA,MACF,CAAA,GAAG;AACH,MAAA,KAAA,CAAM,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,MAAM;AAC5B,QAAA,KAAK,SAAA,CAAU,OAAA,EAAS,OAAA,CAAQ,sBAAA,EAAwB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,OAAO,OAAA,CAAQ,2BAA2B,CAAA,EAAE,EAAG,CAAC,CAAA;AAAA,MAC5I,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAU;AAC3B,QAAA,MAAM,SAAA,GAAY,WAAA,CAAY,KAAA,CAAM,OAAA,EAAS,OAAO,CAAA;AACpD,QAAAA,OAAAA,CAAO,MAAM,yBAAA,EAA2B,EAAE,SAAS,WAAA,EAAa,KAAA,EAAO,WAAW,CAAA;AAClF,QAAA,KAAK,SAAA,CAAU,OAAA,EAAS,OAAA,CAAQ,sBAAA,EAAwB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,KAAA,EAAO,SAAA,EAAU,EAAG,CAAC,CAAA;AAAA,MACjH,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,OAAO,IAAA,KAAS;AAChC,QAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,UAAA,EAAY,SAAS,CAAC,CAAA;AACzC,QAAA,IAAI,OAAA,IAAW,WAAA;AACb,UAAA;AACF,QAAA,IAAI,KAAA;AACF,UAAA,YAAA,CAAa,KAAK,CAAA;AACpB,QAAA,IAAI,CAAE,MAAM,OAAA,CAAQ,UAAA,EAAW,EAAI;AACjC,UAAA,MAAM,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,sBAAA,EAAwB,EAAE,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,OAAO,OAAA,CAAQ,0BAA0B,CAAA,EAAE,EAAG,CAAC,CAAA;AACzI,UAAA;AAAA,QACF;AACA,QAAA,MAAM,WAAW,IAAA,IAAQ,CAAA,CAAA;AACzB,QAAA,IAAI,aAAa,CAAA,EAAG;AAClB,UAAA,MAAA,CAAOF,EAAAA,CAAG,EAAE,IAAA,EAAM,QAAA,EAAU,QAAQ,MAAA,EAAQ,eAAA,EAAiB,eAAA,EAAiB,CAAC,CAAA;AAC/E,UAAA;AAAA,QACF;AACA,QAAAE,OAAAA,CAAO,KAAA,CAAM,mCAAA,EAAqC,EAAE,OAAA,EAAS,WAAA,EAAa,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,WAAA,CAAY,MAAA,EAAQ,OAAO,CAAA,CAAE,MAAM,CAAA,GAAI,CAAA,EAAG,MAAA,EAAQ,WAAA,CAAY,MAAA,EAAQ,OAAO,CAAA,CAAE,KAAA,CAAM,CAAA,GAAK,CAAA,EAAG,eAAA,EAAiB,eAAA,EAAiB,CAAA;AACjO,QAAA,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,sBAAA,EAAwB,EAAE,QAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,KAAA,EAAO,WAAA,CAAY,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,KAAK,CAAC;AAAA,EAAK,UAAU,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,CAAA,EAAI,OAAO,EAAE,KAAA,CAAM,CAAA,GAAK,GAAE,EAAG,GAAG,EAAE,MAAA,EAAQ,QAAQ,gBAAA,EAAkB,WAAA,EAAa,CAAC,CAAA;AAAA,MAC/O,CAAC,CAAA;AACD,MAAA,IAAI,QAAQ,KAAA,KAAU,KAAA,CAAA;AACpB,QAAA,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA;AACjC,MAAA,KAAA,CAAM,MAAM,GAAA,EAAI;AAAA,IAClB,CAAC,CAAA;AAAA,EACH,CAAA,CAAA,MACM;AAEJ,IAAA,OAAO,OAAA,CAAQ,QAAQ,sBAAA,EAAwB,EAAE,QAAQ,EAAE,OAAA,EAAS,aAAa,KAAA,EAAO,OAAA,CAAQ,+BAA+B,CAAA,EAAE,EAAG,CAAA,EAAG,EAAE,QAAQ,eAAA,EAAiB,gBAAA,EAAkB,eAAe,CAAA;AAAA,EACrM;AACF;ACvOO,IAAM,uBAAuB,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAyEpC,IAAM,qBAAqB,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAIvC,UAAA,CAAW,QAAQ,IAAI,CAAA;AAiBlB,IAAM,oBAAA,GAAuB,sPAAA;AAmBpC,SAAS,aAAA,CAAc,GAAA,EAAmE,MAAA,GAAsC,eAAA,EAAmC;AACjK,EAAA,OAAOD,IAAI,EAAE,GAAG,eAAe,qBAAA,EAAuB,OAAA,EAAS,QAAQ,GAAG,CAAA,EAAG,GAAA,EAAK,EAAE,kBAAkB,EAAE,MAAA,EAAQ,kBAAkB,aAAA,EAAc,IAAK,CAAA;AACvJ;AAoBA,eAAsB,iBAAA,CAAkB,QAAA,EAAkB,QAAA,EAAkB,oBAAA,EAA+D;AACzI,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,aAAA;AACJ,EAAA,MAAM,UAAU,MAAuB;AACrC,IAAA,IAAI,CAAC,SAAA,IAAa,CAACV,UAAAA,CAAW,SAAS,CAAA;AACrC,MAAA,OAAOS,GAAG,MAAS,CAAA;AACrB,IAAA,IAAI;AACF,MAAA,IAAIM,UAAU,SAAS,CAAA,CAAE,cAAA,EAAe,IAAKT,QAAQ,YAAA,CAAa,SAAS,CAAC,CAAA,KAAM,iBAAiB,CAAC,QAAA,CAAS,SAAS,CAAA,CAAE,WAAW,kBAAkB,CAAA;AACnJ,QAAA,OAAO,cAAc,gCAAgC,CAAA;AACvD,MAAA,MAAA,CAAO,WAAW,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,OAAO,CAAA;AACnD,MAAA,OAAOG,GAAG,KAAA,CAAS,CAAA;AAAA,IACrB,CAAA,CAAA,MACM;AAAE,MAAA,OAAO,cAAc,gCAAgC,CAAA;AAAA,IAAE;AAAA,EACjE,CAAA;AACA,EAAA,IAAI;AACF,IAAA,aAAA,GAAgB,YAAA,CAAa,QAAQ,CAAA;AACrC,IAAA,IAAI,QAAA,IAAY,YAAY,GAAA,EAAI;AAC9B,MAAA,OAAO,aAAA,CAAc,2BAA2B,SAAS,CAAA;AAC3D,IAAA,IAAI,CAAC,QAAA,IAAY,UAAA,CAAW,IAAA,CAAK,QAAQ,CAAA,IAAK,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,QAAQ,CAAA,CAAE,MAAA,GAAS,IAAA;AACxF,MAAA,OAAO,cAAc,yBAAyB,CAAA;AAChD,IAAA,SAAA,GAAY,WAAA,CAAYJ,IAAAA,CAAK,aAAA,EAAe,kBAAkB,CAAC,CAAA;AAC/D,IAAAW,SAAAA,CAAU,WAAW,GAAK,CAAA;AAC1B,IAAA,IAAIC,OAAAA,GAASZ,IAAAA,CAAK,SAAA,EAAW,YAAY,CAAA;AACzC,IAAA,IAAIF,QAAAA,CAAQ,aAAa,OAAA,EAAS;AAChC,MAAAc,OAAAA,GAASZ,IAAAA,CAAK,SAAA,EAAW,aAAa,CAAA;AACtC,MAAA,MAAM,MAAA,GAASA,IAAAA,CAAK,SAAA,EAAW,YAAY,CAAA;AAC3C,MAAAG,cAAc,MAAA,EAAQ,oBAAA,EAAsB,EAAE,IAAA,EAAM,KAAO,CAAA;AAC3D,MAAA,MAAM,QAAA,GAAWH,KAAKF,QAAAA,CAAQ,GAAA,CAAI,cAAc,aAAA,EAAe,UAAA,EAAY,mBAAA,EAAqB,MAAA,EAAQ,gBAAgB,CAAA;AACxH,MAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,QAAA,EAAU,CAAC,YAAA,EAAc,iBAAA,EAAmB,UAAA,EAAY,oBAAoB,CAAA,EAAG;AAAA,QAC/G,KAAK,EAAE,yBAAA,EAA2B,QAAQ,yBAAA,EAA2Bc,OAAAA,EAAQ,6BAA6B,EAAA,EAAG;AAAA,QAC7G,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,GAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,QAAA,GAAW,WAAA,CAAY,GAAA,EAAK,CAAC,CAAC,CAAA;AAAA,QAChF,oBAAA;AAAA,QACA,OAAA,EAAS,CAAC,QAAQ;AAAA,OACnB,CAAA;AACD,MAAA,IAAI,CAAC,SAAS,OAAA,EAAS;AACrB,QAAA,MAAM,UAAU,OAAA,EAAQ;AACxB,QAAA,OAAO,OAAA,CAAQ,UAAU,QAAA,GAAW,OAAA;AAAA,MACtC;AACA,MAAA,IAAI,CAACjB,UAAAA,CAAWiB,OAAM,CAAA,EAAG;AACvB,QAAA,MAAM,UAAU,OAAA,EAAQ;AACxB,QAAA,OAAO,OAAA,CAAQ,OAAA,GAAU,aAAA,CAAc,yBAAyB,CAAA,GAAI,OAAA;AAAA,MACtE;AAAA,IACF,CAAA,MACK;AACH,MAAAT,cAAcS,OAAAA,EAAQ,kBAAA,EAAoB,EAAE,IAAA,EAAM,KAAO,CAAA;AAAA,IAC3D;AACA,IAAA,IAAI,QAAA,IAAY,WAAA,CAAY,GAAA,EAAI,EAAG;AACjC,MAAA,MAAM,UAAU,OAAA,EAAQ;AACxB,MAAA,OAAO,OAAA,CAAQ,OAAA,GAAU,aAAA,CAAc,yBAAA,EAA2B,SAAS,CAAA,GAAI,OAAA;AAAA,IACjF;AACA,IAAA,OAAOR,GAAG,EAAE,GAAA,EAAK,EAAE,WAAA,EAAaQ,SAAQ,mBAAA,EAAqB,OAAA,EAAS,kBAAA,EAAoB,EAAA,EAAI,SAAS,cAAA,EAAgB,2BAAA,EAA6B,QAAA,EAAS,EAAG,SAAS,CAAA;AAAA,EAC3K,CAAA,CAAA,MACM;AACJ,IAAA,MAAM,UAAU,OAAA,EAAQ;AACxB,IAAA,OAAO,OAAA,CAAQ,OAAA,GAAU,aAAA,CAAc,yBAAyB,CAAA,GAAI,OAAA;AAAA,EACtE;AACF;;;AC3MO,SAAS,kBAAA,GAA6B;AAC3C,EAAA,OAAO,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA8FhB;;;ACzFO,SAAS,cAAc,KAAA,EAAuB;AACnD,EAAA,OAAO,CAAA,CAAA,EAAI,KAAA,CAAM,UAAA,CAAW,GAAA,EAAM,OAAU,CAAC,CAAA,CAAA,CAAA;AAC/C;AAsBO,SAAS,kBAAkB,OAAA,EAWvB;AACT,EAAA,MAAM,MAAA,GAAiC;AAAA,IACrC,EAAA,EAAI,aAAA,CAAc,OAAA,CAAQ,YAAY,CAAA;AAAA,IACtC,OAAA,EAAS,aAAA,CAAc,CAAA,IAAA,EAAO,OAAA,CAAQ,WAAW,CAAA,CAAE,CAAA;AAAA,IACnD,GAAA,EAAK,aAAA,CAAc,OAAA,CAAQ,WAAW,CAAA;AAAA,IACtC,OAAA,EAAS,aAAA,CAAc,OAAA,CAAQ,OAAO,CAAA;AAAA,IACtC,OAAA,EAAS,OAAA,CAAQ,OAAA,GAAU,MAAA,GAAS,OAAA;AAAA,IACpC,UAAU,aAAA,CAAc,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IAClD,IAAA,EAAM,aAAA,CAAc,OAAA,CAAQ,SAAS,CAAA;AAAA,IACrC,IAAA,EAAM,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAC7B,QAAQ,OAAA,CAAQ,WAAA,CAAY,IAAI,aAAa,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,IACvD,OAAA,EAAS,QAAQ,cAAA,IAAkB,MAAA;AAAA,IACnC,QAAQ,kCAAA;AAAmC,GAC7C;AACA,EAAA,OAAO,MAAA,CAAO,GAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","file":"index.js","sourcesContent":["/** 已构建镜像的交付契约;构建器写入,部署器只校验和消费。 */\nimport { createHash } from 'node:crypto'\nimport { createReadStream, existsSync, lstatSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { z } from 'zod'\n\n/**\n * 镜像制品清单,例如 `{ version: 4, primaryService: 'serv', appVersion: '1.2.3', buildId: '1.2.3-build1', partial: false, hasWeb: false, images: [...] }`。\n * 根目录制品保留格式4;非根目录使用格式5,强制旧部署器拒绝而非静默忽略挂载路径。\n * 完整产物包含primaryService,hasWeb记录浏览器端拓扑;结构验证不能代替真实归档校验。\n * @example\n * ```ts\n * import { readFile } from 'node:fs/promises'\n * import { DeploymentArtifactSchema } from '@h-ai/deploy'\n * const content = await readFile('.hai/build/docker/build-id/manifest.json', 'utf8')\n * const parsed = DeploymentArtifactSchema.safeParse(JSON.parse(content))\n * if (!parsed.success) throw new Error('Invalid artifact manifest')\n * // Schema 只验证结构;文件路径与 SHA-256 核验使用 readDeploymentArtifact。\n * ```\n */\nexport const DeploymentArtifactSchema = z.object({\n /** 清单格式版本,与应用版本和部署环境无关。 */\n version: z.union([z.literal(4), z.literal(5)]),\n /** 主运行服务:独立后端为 serv,独立浏览器站点(静态或 SSR)为 web。 */\n primaryService: z.enum(['serv', 'web']),\n /** 应用根 package.json 的版本,用于归档、Compose 与桌面交付;最长 80 字符。 */\n appVersion: z.string().max(80).regex(/^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9a-z-]+(?:\\.[0-9a-z-]+)*)?(?:\\+[0-9a-z-]+(?:\\.[0-9a-z-]+)*)?$/i),\n /** 本次构建标识;同一应用版本允许重复构建。 */\n buildId: z.string().max(128).regex(/^[a-z0-9][\\w.+-]*$/i),\n /** 只包含所选镜像的构建不能用于首次安装。 */\n partial: z.boolean().default(false),\n /** 是否包含浏览器端;仅构建 serv 时也保留完整工程的 Web 拓扑。 */\n hasWeb: z.boolean().default(false),\n /** Web构建的公开挂载目录,无末尾斜杠;省略或空字符串保持域名根目录。增量制品须保留完整拓扑的同一值。 */\n webBasePath: z.string().refine(value => value === '' || (/^\\/[\\w.-]+(?:\\/[\\w.-]+)*$/.test(value) && !value.split('/').some(segment => segment === '.' || segment === '..'))).optional(),\n /** 工程显式配置的后端端口,部分构建未包含 serv 时仍保留。 */\n servContainerPort: z.number().int().min(1).max(65535).optional(),\n /** 工程显式配置的 Web 端口,部分构建未包含 web 镜像时仍保留;缺省使用部署默认值。 */\n webContainerPort: z.number().int().min(1).max(65535).optional(),\n /** 本次构建选择的镜像归档。 */\n images: z.array(z.object({\n /** serv 为独立 API 后端,web 为浏览器站点(静态或 SSR)。 */\n name: z.enum(['serv', 'web']),\n /** 相对于清单目录的 tar 文件名。 */\n file: z.string().regex(/^[\\w.+-]+\\.tar$/),\n /** 归档导入后可直接使用的不可变镜像引用。 */\n imageRef: z.string().regex(/^[a-z0-9][a-z0-9./:_-]*:[a-z0-9_][a-z0-9_.-]*$/).refine(value => !value.endsWith(':latest')),\n /** tar 内容的 SHA-256,用于部署前校验。 */\n sha256: z.string().regex(/^[a-f0-9]{64}$/),\n /** 容器内部监听端口;服务器公开端口由部署选择。 */\n containerPort: z.number().int().min(1).max(65535).optional(),\n })).min(1).max(2).refine(images => new Set(images.map(image => image.name)).size === images.length),\n}).refine(artifact => artifact.version === 5 ? !!artifact.webBasePath : !artifact.webBasePath).refine(artifact => !artifact.webBasePath || artifact.hasWeb).refine(artifact => artifact.images.every(image => image.file === `${image.name}-${artifact.appVersion}.tar`)).refine(artifact => artifact.primaryService !== 'web' || artifact.hasWeb).refine(artifact => artifact.images.every(image => image.name === artifact.primaryService || (image.name === 'web' && artifact.hasWeb))).refine(artifact => artifact.partial || artifact.images.some(image => image.name === artifact.primaryService)).refine(artifact => artifact.partial || !artifact.hasWeb || artifact.images.some(image => image.name === 'web'))\n\n/**\n * 构建器与部署器共享的镜像交付结构;参见 DeploymentArtifactSchema 示例。\n * @example\n * ```ts\n * import type { DeploymentArtifact } from '@h-ai/deploy'\n * import { readDeploymentArtifact } from '@h-ai/deploy'\n * const directory = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(directory)\n * const verified: DeploymentArtifact = artifact\n * const references = verified.images.map(image => image.imageRef)\n * ```\n */\nexport type DeploymentArtifact = z.infer<typeof DeploymentArtifactSchema>\n\n/**\n * 流式计算制品校验和,避免将大镜像一次性读入内存。\n * @throws Error - 文件读取失败;返回真实 tar 内容的 SHA-256,不校验清单其它字段。\n * @param file - 真实镜像归档文件路径。\n * @returns 文件内容的 SHA-256 十六进制摘要。\n * @example\n * ```ts\n * import { artifactChecksum } from '@h-ai/deploy'\n * const digest = await artifactChecksum('.hai/build/docker/build-id/serv-1.0.0.tar')\n * ```\n */\nexport async function artifactChecksum(file: string): Promise<string> {\n const hash = createHash('sha256')\n for await (const chunk of createReadStream(file))\n hash.update(chunk)\n return hash.digest('hex')\n}\n\n/**\n * 校验完整构建产物;缺失、损坏或非法清单均抛错,由部署边界转换为 HaiResult。\n * @throws Error - 清单、路径、镜像 tar 或摘要校验失败;不能用未验证的清单绕过本函数。\n * @param directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @returns 已经验证的构建制品清单。\n * @example\n * ```ts\n * import { readDeploymentArtifact } from '@h-ai/deploy'\n * const directory = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(directory)\n * const images = artifact.images.map(image => ({ name: image.name, imageRef: image.imageRef }))\n * ```\n */\nexport async function readDeploymentArtifact(directory: string): Promise<DeploymentArtifact> {\n const artifact = DeploymentArtifactSchema.parse(JSON.parse(readFileSync(resolve(directory, 'manifest.json'), 'utf8')))\n for (const image of artifact.images) {\n const file = resolve(directory, image.file)\n if (!existsSync(file) || !lstatSync(file).isFile() || lstatSync(file).isSymbolicLink() || await artifactChecksum(file) !== image.sha256)\n throw new Error(`Invalid artifact: ${image.file}`)\n }\n return artifact\n}\n","{\n \"deploy_notInitialized\": \"Deploy module not initialized, call deploy.init() first\",\n \"deploy_initFailed\": \"Deploy module initialization failed: {error}\",\n \"deploy_unsupportedProviderType\": \"Unsupported deploy provider type: {type}\",\n \"deploy_unsupportedProvisionerType\": \"Unsupported service provisioner type: {type}\",\n \"deploy_configTokenRequired\": \"Deploy provider token is required\",\n \"deploy_authRequired\": \"Authentication required\",\n \"deploy_authFailed\": \"Authentication failed: {error}\",\n \"deploy_projectCreateFailed\": \"Project creation failed: {error}\",\n \"deploy_uploadFailed\": \"Build output upload failed: {error}\",\n \"deploy_deployFailed\": \"Deployment failed: {error}\",\n \"deploy_provisionFailed\": \"Service provisioning failed: {service} - {error}\",\n \"deploy_adapterMissing\": \"Target platform adapter not found, please install {adapter}\",\n \"deploy_scanFailed\": \"Application scan failed: {error}\",\n \"deploy_envVarFailed\": \"Environment variable setup failed: {error}\",\n \"deploy_credentialError\": \"Credential read/write failed: {error}\",\n \"deploy_credentialInvalidKey\": \"Unsupported credential key: {key}. Only HAI_DEPLOY_* keys are allowed\",\n \"deploy_credentialSaved\": \"Credentials saved\",\n \"deploy_credentialLoaded\": \"Credentials loaded\",\n \"deploy_configError\": \"Deploy config error: {error}\",\n \"deploy_credentialMissing\": \"Missing credential fields: {fields}\",\n \"deploy_apiError\": \"{service} API error ({status})\",\n \"deploy_fileUploadFailed\": \"File upload failed ({status})\",\n \"deploy_provisionNoResult\": \"No connection info returned from {service}\",\n \"deploy_recoveryFailure\": \"Deployment stopped at {stage}; inspect the recovery details.\",\n \"deploy_recoverySuggestion\": \"Inspect listed resources in the provider console before retrying with the same project name. Unknown means the request may have created a resource. Reused resources are never deleted automatically; remove newly created resources manually only after checking their use.\",\n \"deploy_commandTimeout\": \"Command timed out: {command}\",\n \"deploy_commandFailed\": \"Command failed ({command}): {error}\",\n \"deploy_remoteConnectFailed\": \"Cannot connect to remote host {host}: {error}\",\n \"deploy_remoteRuntimeMissing\": \"Remote host missing container runtime or compose: {runtime}\",\n \"deploy_imageTransferFailed\": \"Image transfer failed: {error}\",\n \"deploy_healthCheckFailed\": \"Health check failed, app not ready at {url}\",\n \"deploy_invalidEnvironment\": \"Use letters, numbers, underscores or hyphens for the environment; local/example are reserved.\",\n \"deploy_environmentMissing\": \"Environment file missing: {path}. Create and configure it before deploying.\",\n \"deploy_environmentReadFailed\": \"Cannot read deployment environment files; check syntax and permissions.\",\n \"deploy_environmentWriteFailed\": \"Cannot save deployment configuration; check file syntax and permissions.\",\n \"deploy_multipleApplications\": \"Multiple service packages found; specify the application directory.\",\n \"deploy_purposeSqlite\": \"Local relational database persisted in a volume\",\n \"deploy_purposeDatabase\": \"Relational database service for business data\",\n \"deploy_purposeMemory\": \"Per-process memory cache; cleared on restart, no external service\",\n \"deploy_purposeLocal\": \"Local filesystem storage persisted in a volume\",\n \"deploy_purposeCache\": \"Shared cache, sessions and distributed locks\",\n \"deploy_purposeStorage\": \"S3-compatible object storage for uploaded files\",\n \"deploy_purposeVector\": \"Vector indexing and similarity search\",\n \"deploy_purposeDisabled\": \"LDAP login is disabled; no directory service is created\",\n \"deploy_purposeLdap\": \"Directory account authentication; the default directory has no business users\",\n \"deploy_purposeConsole\": \"Messages go to application logs without delivery\",\n \"deploy_purposeEmail\": \"Email/HTTP delivery; the default SMTP container only captures test messages\",\n \"deploy_purposeSms\": \"SMS through Aliyun credentials; requires an existing signature and quota\",\n \"deploy_webProxyInvalid\": \"The API prefix must be an absolute path containing only letters, numbers, underscores, hyphens and slashes.\",\n \"deploy_webBaseConflict\": \"The website mount path conflicts with an API or health endpoint. Choose a different PUBLIC_BASE_PATH.\",\n \"deploy_storageProxyInvalid\": \"Cannot generate the storage proxy. Use a valid DNS bucket name whose path does not overlap the website, API, or health endpoints.\",\n \"deploy_storagePublicEndpointInvalid\": \"Invalid storage.publicEndpoint. Use a browser-accessible HTTP(S) address with an optional valid proxy path, without a bucket, credentials, query or fragment.\",\n \"deploy_storageBackendRequired\": \"A static browser app cannot deploy server-side storage credentials. Configure Storage in Serv or SvelteKit and obtain presigned links through its API.\",\n \"deploy_artifactInvalid\": \"Image artifacts are missing or invalid. Run pnpm build --target image, select valid --artifact-dir, or use pnpm run deploy --build.\",\n \"deploy_sshRequired\": \"Automatic deployment requires SSH settings. Use --bundle-only for manual transfer when the server is unreachable.\",\n \"deploy_sshPasswordInvalid\": \"SSH passwords must be nonempty, contain no CR/LF/NUL, and be at most 1023 UTF-8 bytes.\",\n \"deploy_sshAskpassFailed\": \"Could not prepare the managed SSH password helper. Check OpenSSH and Windows PowerShell 5.\",\n \"deploy_sshAskpassCleanupFailed\": \"Could not confirm cleanup of this SSH password helper. Inspect the local temporary directory.\",\n \"deploy_targetAuth\": \"Authentication: key uses a private key or ssh-agent; password reads the local environment variable named by passwordEnv.\",\n \"deploy_targetPasswordEnv\": \"Environment variable name only, never the password. Reuse the operator environment; if missing, the uploader prompts for hidden input for this run only. Defaults to HAI_DEPLOY_PROVIDER_SSH_PASSWORD.\",\n \"deploy_bundleInstructions\": \"Bundle: {file}\\nIncludes all images needed by selected services, including self-hosted middleware.\\nWith SSH access, first edit deploy-target.json in the same delivery directory using its _comments, then run deploy.ps1 (Windows) or deploy.sh (Linux/macOS) there. Both read this JSON; the sh entry also requires local awk.\\nFor isolated servers, copy the entire delivery directory to Linux and run sh deploy-local.sh there. It extracts the archive, applies it and preserves logs. An optional first argument overrides the server deployment directory.\\nLinux requires Docker/Podman, Compose, sh, tar, sha256sum, awk, curl, util-linux flock and filesystem/container permissions on a filesystem supporting flock.\\nNever delete or replace .deploy.lock; its lock releases after every holder exits or the server restarts. Inspect execution and recovery state after forced termination.\\nPartial updates require a successful full installation with matching ports/layout. Steps return nonzero on failure; result-DEPLOYMENT_ID.json records the outcome.\\nThe bundle contains private runtime configuration; transfer it securely.\\nIncluded images:\\n{images}\",\n \"deploy_bundleMetadata\": \"Application version: {version}\\nBuild ID: {buildId}\\nCompose file: {compose}\\nDeployment ID: {deploymentId}\",\n \"deploy_targetHost\": \"Required: Linux server address or SSH alias. Replace SERVER_HOST before running either upload script.\",\n \"deploy_targetPort\": \"SSH port, integer 1-65535; default 22.\",\n \"deploy_targetUsername\": \"SSH login username; default deploy. Requires write access to directory and container runtime permissions.\",\n \"deploy_targetIdentityFile\": \"Optional private key path on the computer running the upload script. Prefer an absolute path; empty uses ssh-agent/default keys. HAI_DEPLOY_IDENTITY_FILE overrides it.\",\n \"deploy_targetKnownHostsFile\": \"Optional known_hosts path on the computer running the upload script. Prefer an absolute path; empty uses OpenSSH defaults. HAI_DEPLOY_KNOWN_HOSTS_FILE overrides it.\",\n \"deploy_targetStrictHostKeyChecking\": \"Boolean, default true: trust new host keys and reject changed keys. false disables host key checking.\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH connection timeout in seconds, integer 1-2147483647; default 10.\",\n \"deploy_targetDirectory\": \"Required absolute application directory on the Linux server; contains incoming packages, releases and successful current state. Parent-directory traversal is forbidden.\",\n \"deploy_targetBundle\": \"Required tar filename in the parent of this deployment directory. Keep the tar and this entire directory together when moving them.\",\n \"deploy_bundleOnlyContainer\": \"Compose bundle generation is supported only by docker-ssh.\",\n \"deploy_selectedContainerOnly\": \"Selected-service deployment requires a docker-ssh Compose destination.\",\n \"deploy_selectionInvalid\": \"Cannot deploy {service}: check the service name and build its image first.\",\n \"deploy_imageVersionRequired\": \"Specify an image version; latest is not allowed: {image}\",\n \"deploy_bundleRuntimeRequired\": \"Start local Podman/Docker to export middleware images, or prepare this complete offline bundle on the build machine.\",\n \"deploy_bundleFailed\": \"Package preparation or deployment failed: {reason}\",\n \"deploy_configFileInvalid\": \"Invalid YAML in {path}, line {line}. Check indentation, colons and quotes.\",\n \"deploy_configFileUnreadable\": \"Cannot read configuration file {path}. Check its path and permissions.\",\n \"deploy_bundleNameInvalid\": \"Bundle filenames may contain letters, numbers, dots, plus signs, hyphens and underscores; parent directories may contain spaces.\",\n \"deploy_localStopped\": \"The local command process tree has been confirmed exited.\",\n \"deploy_localUnknown\": \"Local process tree termination is unconfirmed; inspect local execution state.\",\n \"deploy_localNotStarted\": \"The local command was not started.\",\n \"deploy_commandOutputFailed\": \"Command output or callback failed\",\n \"deploy_commandInputFailed\": \"Command input failed\",\n \"deploy_commandTreeActive\": \"Child processes remain active after the main command exited\",\n \"deploy_commandExecutionFailed\": \"Command execution failed\",\n \"deploy_remoteUnknown\": \"Remote execution is unknown. Local SSH termination does not prove remote deployment stopped; inspect the server result and actual containers.\",\n \"deploy_remoteFinished\": \"A matching server result confirms the deployment script and recovery finished: stage {stage}, exit {code}. Verify actual service health.\",\n \"deploy_bundleDirectoryExists\": \"Delivery directory already exists: {path}. Choose another output name to preserve the existing bundle.\",\n \"deploy_bundleFull\": \"Full deployment\",\n \"deploy_bundlePartial\": \"Partial deployment (requires a successful full baseline)\",\n \"deploy_bundleSelection\": \"Deployment mode: {mode}\\nSelected services: {services}; see partial and selectedServices in manifest.json.\",\n \"deploy_transportBodyLimitInvalid\": \"Invalid transport.maxPlaintextBytes: use an integer from 1024 to 67108864 bytes\",\n \"deploy_transportKeyRingInvalid\": \"The transport key ring is missing or invalid; the application has not been uploaded. Set HAI_CRYPTO_TRANSPORT_SERVERKEYRING in {path} or the deployment process using complete valid JSON, and distribute the same managed ring to every node.\",\n \"deploy_uploadPasswordPrompt\": \"Enter SSH password (hidden)\",\n \"deploy_uploadPasswordUnavailable\": \"Interactive password input is unavailable. Set this operator environment variable before running the deployment script again.\",\n \"deploy_uploadPasswordCancelled\": \"Password input cancelled; no server connection was made.\",\n \"deploy_uploadPasswordInvalid\": \"SSH passwords must contain 1–1023 UTF-8 bytes without line breaks.\",\n \"deploy_managedSecretsInvalid\": \"Invalid generated middleware credential candidates. Rebuild the deployment bundle; server credentials will not be rotated automatically.\",\n \"deploy_secretImportFailed\": \"Legacy credential import was rejected during {phase}; check private input permissions, project/volume identity, live credentials and the deployment lock. No services were updated; inspect the protected state file if commit is unconfirmed\",\n \"deploy_projectNameRequired\": \"The root package.json.name is missing or cannot be normalized into an image and deployment resource identity.\",\n \"deploy_projectNameOverrideRemoved\": \"Deployment identity comes from the root package.json.name; remove the obsolete projectName override.\",\n \"deploy_requestAccessInvalid\": \"Invalid request access policy ({field}). Check fields, IP addresses, timezones and time windows. For a file reference, use readable YAML no larger than 1 MiB. Fix the configuration and create a new bundle.\",\n \"deploy_httpsPortsInvalid\": \"HTTP and HTTPS ports must differ; Let’s Encrypt HTTP-01 requires host port 80.\",\n \"deploy_httpsCertificateInvalid\": \"Invalid HTTPS certificate. Check readable PEM files, matching unencrypted private key, validity dates and domain, then repackage.\"\n}\n","{\n \"deploy_notInitialized\": \"デプロイモジュールが初期化されていません。先にdeploy.init()を呼び出してください\",\n \"deploy_initFailed\": \"デプロイモジュールの初期化に失敗しました: {error}\",\n \"deploy_unsupportedProviderType\": \"未対応のデプロイプロバイダーの種類です: {type}\",\n \"deploy_unsupportedProvisionerType\": \"未対応のサービスプロビジョナーの種類です: {type}\",\n \"deploy_configTokenRequired\": \"デプロイプロバイダーのトークンは必須です\",\n \"deploy_authRequired\": \"認証が必要です\",\n \"deploy_authFailed\": \"認証に失敗しました: {error}\",\n \"deploy_projectCreateFailed\": \"プロジェクトの作成に失敗しました: {error}\",\n \"deploy_uploadFailed\": \"ビルド成果物のアップロードに失敗しました: {error}\",\n \"deploy_deployFailed\": \"デプロイに失敗しました: {error}\",\n \"deploy_provisionFailed\": \"サービスの準備に失敗しました: {service} - {error}\",\n \"deploy_adapterMissing\": \"対象プラットフォームのアダプターが見つかりません。{adapter}をインストールしてください\",\n \"deploy_scanFailed\": \"アプリケーションのスキャンに失敗しました: {error}\",\n \"deploy_envVarFailed\": \"環境変数の設定に失敗しました: {error}\",\n \"deploy_credentialError\": \"認証情報の読み書きに失敗しました: {error}\",\n \"deploy_credentialInvalidKey\": \"未対応の認証情報キーです: {key}。HAI_DEPLOY_*キーのみ使用できます\",\n \"deploy_credentialSaved\": \"認証情報を保存しました\",\n \"deploy_credentialLoaded\": \"認証情報を読み込みました\",\n \"deploy_configError\": \"デプロイ設定エラー: {error}\",\n \"deploy_credentialMissing\": \"認証情報の項目が不足しています: {fields}\",\n \"deploy_apiError\": \"{service} APIエラー({status})\",\n \"deploy_fileUploadFailed\": \"ファイルのアップロードに失敗しました({status})\",\n \"deploy_provisionNoResult\": \"{service}から接続情報が返されませんでした\",\n \"deploy_recoveryFailure\": \"{stage}でデプロイを停止しました。復旧情報を確認してください。\",\n \"deploy_recoverySuggestion\": \"同じプロジェクト名で再試行する前に、プロバイダーのコンソールで記載されたリソースを確認してください。「不明」は、リクエストによってリソースが作成された可能性を示します。再利用したリソースは自動削除されません。新規リソースは使用状況を確認してから手動で削除してください。\",\n \"deploy_commandTimeout\": \"コマンドがタイムアウトしました: {command}\",\n \"deploy_commandFailed\": \"コマンドに失敗しました({command}): {error}\",\n \"deploy_remoteConnectFailed\": \"リモートホスト{host}に接続できません: {error}\",\n \"deploy_remoteRuntimeMissing\": \"リモートホストにコンテナーランタイムまたはcomposeがありません: {runtime}\",\n \"deploy_imageTransferFailed\": \"イメージの転送に失敗しました: {error}\",\n \"deploy_healthCheckFailed\": \"ヘルスチェックに失敗しました。{url}でアプリの準備が完了していません\",\n \"deploy_invalidEnvironment\": \"環境名には英数字、アンダースコア、ハイフンを使用してください。local/exampleは予約されています。\",\n \"deploy_environmentMissing\": \"環境ファイルがありません: {path}。デプロイ前に作成して設定してください。\",\n \"deploy_environmentReadFailed\": \"デプロイ用の環境ファイルを読み取れません。構文と権限を確認してください。\",\n \"deploy_environmentWriteFailed\": \"デプロイ設定を保存できません。ファイルの構文と権限を確認してください。\",\n \"deploy_multipleApplications\": \"サービスパッケージが複数見つかりました。アプリケーションのディレクトリを指定してください。\",\n \"deploy_purposeSqlite\": \"ボリュームに永続化するローカルリレーショナルデータベース\",\n \"deploy_purposeDatabase\": \"業務データ用のリレーショナルデータベースサービス\",\n \"deploy_purposeMemory\": \"プロセス単位のメモリーキャッシュ。再起動時に消去され、外部サービスは使用しません\",\n \"deploy_purposeLocal\": \"ボリュームに永続化するローカルファイルストレージ\",\n \"deploy_purposeCache\": \"共有キャッシュ、セッション、分散ロック\",\n \"deploy_purposeStorage\": \"アップロードファイル用のS3互換オブジェクトストレージ\",\n \"deploy_purposeVector\": \"ベクトルのインデックス作成と類似検索\",\n \"deploy_purposeDisabled\": \"LDAPログインは無効です。ディレクトリサービスは作成しません\",\n \"deploy_purposeLdap\": \"ディレクトリアカウント認証。既定のディレクトリには業務ユーザーはいません\",\n \"deploy_purposeConsole\": \"配信せず、アプリケーションログにメッセージを出力します\",\n \"deploy_purposeEmail\": \"メール/HTTP配信。既定のSMTPコンテナーはテストメッセージのみ受信します\",\n \"deploy_purposeSms\": \"Aliyunの認証情報によるSMS。既存の署名と利用枠が必要です\",\n \"deploy_webProxyInvalid\": \"APIプレフィックスは、英数字、アンダースコア、ハイフン、スラッシュのみを含む絶対パスで指定してください。\",\n \"deploy_webBaseConflict\": \"サイトのマウントパスがAPIまたはヘルスチェックと競合しています。別のPUBLIC_BASE_PATHを指定してください。\",\n \"deploy_storageProxyInvalid\": \"ストレージプロキシを生成できません。有効な DNS バケット名を指定し、サイト、API、ヘルスチェックのパスとの重複を避けてください。\",\n \"deploy_storagePublicEndpointInvalid\": \"storage.publicEndpoint が無効です。ブラウザーから到達可能な HTTP(S) アドレスに有効なプロキシパスを指定できます。バケット、認証情報、クエリ、フラグメントは含めないでください。\",\n \"deploy_storageBackendRequired\": \"静的ブラウザアプリにはサーバー用ストレージ認証情報を配置できません。Serv または SvelteKit で Storage を設定し、API 経由で署名付きリンクを取得してください。\",\n \"deploy_artifactInvalid\": \"イメージ成果物が存在しないか、無効です。pnpm build --target image を実行するか、--artifact-dir で有効な成果物を選択するか、pnpm run deploy --build を使用してください。\",\n \"deploy_sshRequired\": \"自動デプロイにはSSH設定が必要です。サーバーに接続できない場合は--bundle-onlyで手動転送用のバンドルを生成してください。\",\n \"deploy_sshPasswordInvalid\": \"SSHパスワードは空にできず、CR/LF/NULを含められません。UTF-8で1023バイト以下にしてください。\",\n \"deploy_sshAskpassFailed\": \"管理対象のSSHパスワードhelperを準備できません。OpenSSHとWindows PowerShell 5を確認してください。\",\n \"deploy_sshAskpassCleanupFailed\": \"今回のSSHパスワードhelperの削除を確認できませんでした。ローカル一時ディレクトリを確認してください。\",\n \"deploy_targetAuth\": \"認証方式:keyは秘密鍵またはssh-agent、passwordはpasswordEnvが指定するローカル環境変数を使用します。\",\n \"deploy_targetPasswordEnv\": \"値ではなく環境変数名だけを保存します。操作端末の環境を優先し、不足時は今回だけ非表示で入力します。既定値は HAI_DEPLOY_PROVIDER_SSH_PASSWORD です。\",\n \"deploy_bundleInstructions\": \"バンドル:{file}\\n選択したサービスに必要なすべてのイメージを含みます(セルフホストのミドルウェアを含む)。\\nSSH を使用する場合、同じ交付ディレクトリの deploy-target.json を _comments に従って編集し、同じ場所で deploy.ps1(Windows)または deploy.sh(Linux/macOS)を実行してください。両方ともこの JSON を読み込みます。sh の実行にはローカルの awk も必要です。\\n隔離されたサーバーには交付ディレクトリ全体をコピーし、sh deploy-local.sh を実行します。自動展開と配置を実行し、ログを保持します。第1引数でサーバーの配置先を上書きできます。\\nLinux には Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux の flock が必要です。flock に対応したファイルシステム上で、ファイルシステムとコンテナーの操作権限も必要です。\\n.deploy.lock は削除も置換もしないでください。すべての保持プロセスが終了するか、サーバーが再起動するとロックが解放されます。強制終了後は実行状態と復旧状態を確認してください。\\n部分更新にはポートと構成が一致する正常な完全インストールが必要です。各手順は失敗時に非ゼロで終了し、result-DEPLOYMENT_ID.json に結果を記録します。\\nバンドルには非公開の実行時設定が含まれます。安全に転送してください。\\n同梱イメージ:\\n{images}\",\n \"deploy_bundleMetadata\": \"アプリのバージョン: {version}\\nビルドID: {buildId}\\nComposeファイル: {compose}\\nデプロイ ID: {deploymentId}\",\n \"deploy_targetHost\": \"必須:Linux サーバーのアドレスまたは SSH エイリアス。アップロードスクリプトを実行する前に SERVER_HOST を置き換えてください。\",\n \"deploy_targetPort\": \"SSH ポート。1〜65535の整数。既定値は22です。\",\n \"deploy_targetUsername\": \"SSH ログインユーザー名。既定値は deploy です。対象ディレクトリへの書き込み権限とコンテナーランタイムの操作権限が必要です。\",\n \"deploy_targetIdentityFile\": \"アップロードスクリプトを実行する端末上の秘密鍵パス(省略可)。絶対パスを推奨します。空欄では ssh-agent または既定の鍵を使用します。HAI_DEPLOY_IDENTITY_FILE で上書きできます。\",\n \"deploy_targetKnownHostsFile\": \"アップロードスクリプトを実行する端末上の known_hosts パス(省略可)。絶対パスを推奨します。空欄では OpenSSH の既定値を使用します。HAI_DEPLOY_KNOWN_HOSTS_FILE で上書きできます。\",\n \"deploy_targetStrictHostKeyChecking\": \"真偽値。既定値の true は新しいホスト鍵を信頼し、変更された鍵を拒否します。false はホスト鍵の検証を無効にします。\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH 接続タイムアウト(秒)。1〜2147483647の整数。既定値は10です。\",\n \"deploy_targetDirectory\": \"必須:Linux サーバー上のアプリケーションの絶対ディレクトリ。受信パッケージ、リリース、成功時の current 状態を保存します。親ディレクトリへの移動は許可されません。\",\n \"deploy_targetBundle\": \"必須:このデプロイディレクトリの親にある tar ファイル名。移動時は tar とこのディレクトリ全体を一緒に移動してください。\",\n \"deploy_bundleOnlyContainer\": \"Composeバンドルの生成はdocker-sshのみでサポートされます。\",\n \"deploy_selectedContainerOnly\": \"サービスを選択したデプロイには docker-ssh Compose のデプロイ先が必要です。\",\n \"deploy_selectionInvalid\": \"{service} をデプロイできません。サービス名を確認し、先にイメージをビルドしてください。\",\n \"deploy_imageVersionRequired\": \"イメージのバージョンを指定してください。latest は使用できません:{image}\",\n \"deploy_bundleRuntimeRequired\": \"ミドルウェアイメージをエクスポートするにはローカルの Podman/Docker を起動するか、ビルド端末で完全なオフラインバンドルを作成してください。\",\n \"deploy_bundleFailed\": \"パッケージの準備またはデプロイに失敗しました:{reason}\",\n \"deploy_configFileInvalid\": \"{path} の {line} 行目の YAML が無効です。インデント、コロン、引用符を確認してください。\",\n \"deploy_configFileUnreadable\": \"設定ファイル {path} を読み込めません。パスと権限を確認してください。\",\n \"deploy_bundleNameInvalid\": \"バンドルのファイル名には英数字、ドット、プラス、ハイフン、アンダースコアを使用できます。親ディレクトリには空白を使用できます。\",\n \"deploy_localStopped\": \"ローカルコマンドのプロセスツリーの終了を確認しました。\",\n \"deploy_localUnknown\": \"ローカルプロセスツリーの終了は未確認です。ローカルの実行状態を確認してください。\",\n \"deploy_localNotStarted\": \"ローカルコマンドは起動していません。\",\n \"deploy_commandOutputFailed\": \"コマンド出力またはコールバックに失敗しました\",\n \"deploy_commandInputFailed\": \"コマンド入力に失敗しました\",\n \"deploy_commandTreeActive\": \"メインコマンド終了後も子プロセスが動作しています\",\n \"deploy_commandExecutionFailed\": \"コマンドの実行に失敗しました\",\n \"deploy_remoteUnknown\": \"リモートの実行状態は不明です。ローカル SSH の終了はリモートデプロイの停止を意味しません。サーバーの結果と実際のコンテナーを確認してください。\",\n \"deploy_remoteFinished\": \"対応するサーバーの結果により、デプロイスクリプトと復旧処理の終了を確認しました:段階 {stage}、終了コード {code}。実際のサービスの稼働状態を確認してください。\",\n \"deploy_bundleDirectoryExists\": \"交付ディレクトリは既に存在します: {path}。既存のバンドルを保持するため別の出力名を選択してください。\",\n \"deploy_bundleFull\": \"完全デプロイ\",\n \"deploy_bundlePartial\": \"部分デプロイ(正常な完全配置の基準が必要)\",\n \"deploy_bundleSelection\": \"デプロイ方式: {mode}\\n更新サービス: {services}。manifest.json の partial と selectedServices で確認できます。\",\n \"deploy_transportBodyLimitInvalid\": \"transport.maxPlaintextBytes は 1024 から 67108864 バイトの整数で指定してください\",\n \"deploy_transportKeyRingInvalid\": \"転送鍵リングが不足または不正のため、アプリはまだアップロードしていません。{path} またはデプロイプロセスの HAI_CRYPTO_TRANSPORT_SERVERKEYRING に完全で有効な JSON を設定し、全ノードに同じ管理リングを配布してください。\",\n \"deploy_uploadPasswordPrompt\": \"SSH パスワードを入力(非表示)\",\n \"deploy_uploadPasswordUnavailable\": \"対話入力を利用できません。この操作端末の環境変数を設定してから配置スクリプトを再実行してください。\",\n \"deploy_uploadPasswordCancelled\": \"パスワード入力を中止しました。サーバーには未接続です。\",\n \"deploy_uploadPasswordInvalid\": \"SSH パスワードは改行を含まない 1–1023 UTF-8 バイトにしてください。\",\n \"deploy_managedSecretsInvalid\": \"自建ミドルウェアの候補認証情報が無効です。配置パッケージを再生成してください。サーバーの認証情報は自動変更されません。\",\n \"deploy_secretImportFailed\": \"旧認証情報のインポートは {phase} 段階で拒否されました。入力権限、プロジェクトとボリューム、実際の認証情報、デプロイロックを確認してください。サービスは更新されていません。確定が不明な場合は保護された状態ファイルを確認してください\",\n \"deploy_projectNameRequired\": \"工程ルートの package.json.name がないか正規化できないため、イメージとデプロイリソースの識別名を生成できません。\",\n \"deploy_projectNameOverrideRemoved\": \"デプロイ識別名は工程ルートの package.json.name から取得します。旧 projectName 上書き引数を削除してください。\",\n \"deploy_requestAccessInvalid\": \"リクエストアクセス設定({field})が無効です。フィールド、IP、タイムゾーン、時間帯を確認してください。ファイルは読み取り可能な 1 MiB 以下の YAML を指定し、修正後に再パッケージしてください。\",\n \"deploy_httpsPortsInvalid\": \"HTTP と HTTPS のポートは異なる必要があります。Let’s Encrypt HTTP-01 にはホストのポート 80 が必要です。\",\n \"deploy_httpsCertificateInvalid\": \"HTTPS 証明書が無効です。PEM ファイル、暗号化されていない秘密鍵との一致、有効期間、ドメインを確認し、再作成してください。\"\n}\n","{\n \"deploy_notInitialized\": \"Deploy 模块尚未初始化,请先调用 deploy.init()\",\n \"deploy_initFailed\": \"Deploy 模块初始化失败:{error}\",\n \"deploy_unsupportedProviderType\": \"不支持的部署平台类型:{type}\",\n \"deploy_unsupportedProvisionerType\": \"不支持的服务 Provisioner 类型:{type}\",\n \"deploy_configTokenRequired\": \"部署平台 Token 不能为空\",\n \"deploy_authRequired\": \"请先完成认证\",\n \"deploy_authFailed\": \"认证失败:{error}\",\n \"deploy_projectCreateFailed\": \"项目创建失败:{error}\",\n \"deploy_uploadFailed\": \"构建产物上传失败:{error}\",\n \"deploy_deployFailed\": \"部署失败:{error}\",\n \"deploy_provisionFailed\": \"基础设施开通失败:{service} - {error}\",\n \"deploy_adapterMissing\": \"未检测到目标平台 adapter,请安装 {adapter}\",\n \"deploy_scanFailed\": \"应用扫描失败:{error}\",\n \"deploy_envVarFailed\": \"环境变量设置失败:{error}\",\n \"deploy_credentialError\": \"凭证读写失败:{error}\",\n \"deploy_credentialInvalidKey\": \"不支持的凭证键名:{key}。仅允许 HAI_DEPLOY_*\",\n \"deploy_credentialSaved\": \"凭证已保存\",\n \"deploy_credentialLoaded\": \"凭证已加载\",\n \"deploy_configError\": \"部署配置错误:{error}\",\n \"deploy_credentialMissing\": \"缺少凭证字段:{fields}\",\n \"deploy_apiError\": \"{service} API 请求失败({status})\",\n \"deploy_fileUploadFailed\": \"文件上传失败({status})\",\n \"deploy_provisionNoResult\": \"{service} 未返回连接信息\",\n \"deploy_recoveryFailure\": \"部署在 {stage} 阶段停止,请查看恢复清单。\",\n \"deploy_recoverySuggestion\": \"重试前在服务商控制台核对清单,并使用相同项目名。unknown 表示请求可能已创建资源。复用资源不会自动删除;新建资源仅在确认未被使用后人工清理。\",\n \"deploy_commandTimeout\": \"命令执行超时:{command}\",\n \"deploy_commandFailed\": \"命令执行失败({command}):{error}\",\n \"deploy_remoteConnectFailed\": \"无法连接远程主机 {host}:{error}\",\n \"deploy_remoteRuntimeMissing\": \"远程主机缺少容器运行时或 compose:{runtime}\",\n \"deploy_imageTransferFailed\": \"镜像传输失败:{error}\",\n \"deploy_healthCheckFailed\": \"健康检查失败,应用未在 {url} 就绪\",\n \"deploy_invalidEnvironment\": \"环境名称仅允许字母、数字、下划线和连字符,且不能使用 local/example。\",\n \"deploy_environmentMissing\": \"缺少环境配置 {path};请先创建该文件并完成配置,再重新部署。\",\n \"deploy_environmentReadFailed\": \"部署环境文件读取失败,请检查文件格式与权限。\",\n \"deploy_environmentWriteFailed\": \"部署配置写入失败,请检查文件格式与权限。\",\n \"deploy_multipleApplications\": \"发现多个服务包,请指定要部署的应用目录。\",\n \"deploy_purposeSqlite\": \"本地文件关系数据库,使用持久化卷\",\n \"deploy_purposeDatabase\": \"独立关系数据库服务,保存业务数据\",\n \"deploy_purposeMemory\": \"单进程内存缓存,重启后清空,不创建外部服务\",\n \"deploy_purposeLocal\": \"本地文件存储,使用持久化卷\",\n \"deploy_purposeCache\": \"共享缓存、会话与分布式锁\",\n \"deploy_purposeStorage\": \"S3 兼容对象存储,保存上传文件\",\n \"deploy_purposeVector\": \"向量索引与相似度搜索\",\n \"deploy_purposeDisabled\": \"LDAP 登录未启用,不创建目录服务\",\n \"deploy_purposeLdap\": \"企业目录账号认证;默认目录不包含业务用户\",\n \"deploy_purposeConsole\": \"消息输出到应用日志,不实际投递\",\n \"deploy_purposeEmail\": \"邮件或 HTTP 通知投递;默认 SMTP 容器仅用于测试接收\",\n \"deploy_purposeSms\": \"通过阿里云凭证接入短信服务,需已有签名与额度\",\n \"deploy_webProxyInvalid\": \"API 前缀必须是仅含字母、数字、下划线、连字符和斜杠的绝对路径。\",\n \"deploy_webBaseConflict\": \"网站挂载目录与 API 或健康检查入口冲突,请使用不同的 PUBLIC_BASE_PATH。\",\n \"deploy_storageProxyInvalid\": \"无法生成对象存储代理:请使用有效的 DNS 桶名,并确保桶路径不与网站目录、API 或健康检查入口重叠。\",\n \"deploy_storagePublicEndpointInvalid\": \"storage.publicEndpoint 无效:请填写浏览器可访问的 HTTP(S) 地址,可包含规范的代理目录,不能包含桶名、凭据、查询或片段。\",\n \"deploy_storageBackendRequired\": \"静态浏览器应用不能部署存储服务端配置。请在 Serv 或 SvelteKit 服务中配置 Storage,再通过 API 获取预签名链接。\",\n \"deploy_artifactInvalid\": \"镜像产物缺失或校验失败。请先执行 pnpm build --target image,或用 --artifact-dir 指定有效产物;也可用 pnpm run deploy --build 一次完成。\",\n \"deploy_sshRequired\": \"自动部署需要 SSH 配置;无网络连接时使用 --bundle-only 生成部署包并手工搬运。\",\n \"deploy_sshPasswordInvalid\": \"SSH 密码不能为空或包含 CR/LF/NUL,UTF-8 长度不能超过 1023 字节。\",\n \"deploy_sshAskpassFailed\": \"无法准备受控 SSH 密码 helper;请检查系统 OpenSSH 和 Windows PowerShell 5。\",\n \"deploy_sshAskpassCleanupFailed\": \"无法确认本次 SSH 密码 helper 已清理,请检查本机临时目录。\",\n \"deploy_targetAuth\": \"认证方式:key 使用私钥或 ssh-agent;password 从 passwordEnv 指定的本机环境读取密码。\",\n \"deploy_targetPasswordEnv\": \"仅保存环境变量名,不是密码值。优先复用操作机环境变量;缺失时部署入口隐藏输入,仅本次使用。默认 HAI_DEPLOY_PROVIDER_SSH_PASSWORD。\",\n \"deploy_bundleInstructions\": \"部署包:{file}\\n包中已包含本次选择服务需要的镜像,包括自建中间件。\\n有 SSH 连接时,先按 _comments 说明修改同一交付目录中的 deploy-target.json,再运行同目录的 deploy.ps1(Windows)或 deploy.sh(Linux/macOS);两者均读取此 JSON,sh 入口还需本机安装 awk。\\n完全隔离时,把整个交付目录复制到 Linux 服务器,在该目录执行 sh deploy-local.sh;脚本自动解包、部署并保留日志。可传入第一个参数覆盖服务器部署目录。\\n服务器需要 Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux flock,以及支持 flock 的文件系统和目录、容器运行权限。\\n固定锁文件 .deploy.lock 禁止删除或替换;全部持有进程退出或重启后自动释放。强杀后的执行与恢复状态须人工核对。\\n部分更新要求服务器已有成功的完整部署,端口及应用布局保持一致。每步失败会返回非零退出码;结果记录在部署目录 result-部署ID.json。\\n包包含私有运行配置,请安全传输。\\n所含镜像:\\n{images}\",\n \"deploy_bundleMetadata\": \"应用版本:{version}\\n构建编号:{buildId}\\nCompose 文件:{compose}\\n部署 ID: {deploymentId}\",\n \"deploy_targetHost\": \"必填:Linux 服务器地址或 SSH 别名。执行任一上传脚本前,将 SERVER_HOST 改为实际地址。\",\n \"deploy_targetPort\": \"SSH 端口,1-65535 的整数,默认 22。\",\n \"deploy_targetUsername\": \"SSH 登录用户名,默认 deploy;需要目标目录写入权限及容器运行权限。\",\n \"deploy_targetIdentityFile\": \"可选:运行上传脚本的电脑上的私钥路径,建议绝对路径;留空使用 ssh-agent 或默认密钥。HAI_DEPLOY_IDENTITY_FILE 可覆盖。\",\n \"deploy_targetKnownHostsFile\": \"可选:运行上传脚本的电脑上的 known_hosts 路径,建议绝对路径;留空使用 OpenSSH 默认文件。HAI_DEPLOY_KNOWN_HOSTS_FILE 可覆盖。\",\n \"deploy_targetStrictHostKeyChecking\": \"布尔值,默认 true:首次信任新主机密钥,拒绝已变更密钥;false 关闭主机密钥检查。\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH 连接超时秒数,1-2147483647 的整数,默认 10。\",\n \"deploy_targetDirectory\": \"必填:Linux 服务器上的应用绝对目录,保存 incoming 部署包、releases 及成功状态 current;禁止 .. 父目录跳转。\",\n \"deploy_targetBundle\": \"必填:本部署操作目录上一级的 tar 文件名;搬运时请将 tar 和本目录完整放在一起。\",\n \"deploy_bundleOnlyContainer\": \"仅生成 Compose tar 只支持 docker-ssh。\",\n \"deploy_selectedContainerOnly\": \"按服务局部部署仅适用于 docker-ssh Compose 目标。\",\n \"deploy_selectionInvalid\": \"无法部署服务 {service}:请检查服务名称,并先构建对应镜像。\",\n \"deploy_imageVersionRequired\": \"镜像必须指定版本,不能使用 latest:{image}\",\n \"deploy_bundleRuntimeRequired\": \"完整离线包需要导出中间件镜像。请启动本地 Podman/Docker,或在构建机打包。\",\n \"deploy_bundleFailed\": \"交付准备或部署失败:{reason}\",\n \"deploy_configFileInvalid\": \"配置文件 {path} 第 {line} 行格式有误。请检查缩进、冒号和引号后重试。\",\n \"deploy_configFileUnreadable\": \"无法读取配置文件 {path},请检查文件路径与读取权限。\",\n \"deploy_bundleNameInvalid\": \"部署包文件名只支持字母、数字、点、加号、短横线和下划线;所在目录可以包含空格。\",\n \"deploy_localStopped\": \"已确认本地命令进程树全部退出。\",\n \"deploy_localUnknown\": \"无法确认本地命令进程树已全部退出;请检查本机执行状态。\",\n \"deploy_localNotStarted\": \"本地命令尚未启动。\",\n \"deploy_commandOutputFailed\": \"命令输出或回调失败\",\n \"deploy_commandInputFailed\": \"命令输入失败\",\n \"deploy_commandTreeActive\": \"主命令退出后仍有活跃的子进程\",\n \"deploy_commandExecutionFailed\": \"命令执行失败\",\n \"deploy_remoteUnknown\": \"远端执行状态未知;本地 SSH 结束不证明远端部署已停止,请核对服务器结果与实际容器状态。\",\n \"deploy_remoteFinished\": \"匹配的服务器结果确认部署脚本及恢复已结束:阶段 {stage},退出码 {code}。请核对实际服务健康状态。\",\n \"deploy_bundleDirectoryExists\": \"交付目录已存在:{path}。请换一个输出名称,保留已有部署包。\",\n \"deploy_bundleFull\": \"全量部署\",\n \"deploy_bundlePartial\": \"增量部署(要求已有成功的全量基线)\",\n \"deploy_bundleSelection\": \"部署模式:{mode}\\n更新服务:{services};可在 manifest.json 中核对 partial 和 selectedServices。\",\n \"deploy_transportBodyLimitInvalid\": \"transport.maxPlaintextBytes 无效:必须是 1024 到 67108864 字节之间的整数\",\n \"deploy_transportKeyRingInvalid\": \"传输密钥环缺失或无效,尚未上传应用。请在 {path} 或部署进程中设置 HAI_CRYPTO_TRANSPORT_SERVERKEYRING,使用完整有效的 JSON,并向所有节点分发同一受管密钥环。\",\n \"deploy_uploadPasswordPrompt\": \"请输入 SSH 密码(隐藏输入)\",\n \"deploy_uploadPasswordUnavailable\": \"当前无法交互输入密码;请先设置该操作机环境变量,再重新运行部署脚本。\",\n \"deploy_uploadPasswordCancelled\": \"已取消密码输入,尚未连接服务器。\",\n \"deploy_uploadPasswordInvalid\": \"SSH 密码须为 1–1023 个 UTF-8 字节,且不能包含换行。\",\n \"deploy_managedSecretsInvalid\": \"自建中间件候选凭据无效,请重新生成部署包;服务器凭据不会自动更换。\",\n \"deploy_secretImportFailed\": \"旧凭据导入在 {phase} 阶段被拒绝;请核对私有输入权限、项目/卷身份、实际服务凭据及部署锁,未执行服务更新;提交结果不明时请核对受保护的状态文件\",\n \"deploy_projectNameRequired\": \"工程根 package.json.name 缺失或无法归一化,不能生成镜像与部署资源身份。\",\n \"deploy_projectNameOverrideRemoved\": \"部署项目名统一来自工程根 package.json.name;请移除旧 projectName 覆盖参数。\",\n \"deploy_requestAccessInvalid\": \"请求访问策略配置无效({field})。请检查字段、IP、时区及时间窗口;如引用文件,请确认文件可读、格式为 YAML 且不超过 1 MiB。修正后重新打包。\",\n \"deploy_httpsPortsInvalid\": \"HTTP 与 HTTPS 端口必须不同;Let’s Encrypt 的 HTTP-01 入口必须使用宿主机 80 端口。\",\n \"deploy_httpsCertificateInvalid\": \"HTTPS 证书无效:请核对 PEM 文件可读、证书与未加密私钥匹配、证书有效期及域名,然后重新打包。\"\n}\n","/**\n * @h-ai/deploy — i18n\n *\n * 本文件提供部署模块的 i18n 文案访问入口。\n * @module deploy-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesJaJP from '../messages/ja-JP.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\n// ─── i18n ───\n\n/**\n * 部署模块文案 Key 类型\n * 从现有中文字典推导消息键,避免内部实现使用未注册的翻译。\n * @example 模块内部上下文\n * ```ts\n * const key: DeployMessageKey = 'deploy_notInitialized'\n * const message = deployM(key)\n * ```\n */\ntype DeployMessageKey = keyof typeof messagesZhCN\n\n/**\n * 获取部署模块文案\n * 使用 core 请求/全局 locale 的现有中英字典;不自行缓存调用时的语言。\n * @param key - 文案 Key\n * @param options - 插值参数与格式化选项\n * @returns 本地化后的文案字符串\n * @example 模块内部上下文\n * ```ts\n * const message = deployM('deploy_sshRequired')\n * ```\n */\nexport const deployM = core.i18n.createMessageGetter<DeployMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n 'ja-JP': messagesJaJP,\n})\n","/**\n * @h-ai/deploy — 部署配置 Schema\n *\n * 本文件定义部署模块的 Zod Schema 和配置类型;错误定义位于 deploy-types.ts。\n * @module deploy-config\n */\n\nimport { z } from 'zod'\nimport { deployM } from './deploy-i18n.js'\n\n// ─── Provider 配置 Schema ───\n\n/** Vercel 部署平台配置 */\nconst VercelProviderConfigSchema = z.object({\n type: z.literal('vercel'),\n token: z.string().min(1, deployM('deploy_configTokenRequired')),\n})\n\n/** SSH 连接配置(docker-ssh Provider 使用 OpenSSH 客户端连接远程主机) */\nconst SshConfigSchema = z.object({\n /** 远程主机地址或 ~/.ssh/config 中的 Host 别名 */\n host: z.string().regex(/^[a-z0-9][a-z0-9.:-]*$/i),\n /** SSH 端口 */\n port: z.number().int().min(1).max(65535).default(22),\n /** SSH 用户名 */\n username: z.string().regex(/^[a-z_][\\w-]*$/i),\n /** 认证方式;省略时非空 password 使用密码,否则保留私钥/agent;显式 key 忽略残留密码。 */\n auth: z.enum(['key', 'password']).optional(),\n /** SSH 密码(保留原值);密码方式必须非空、无 CR/LF/NUL,UTF-8 不超过 1023 字节。 */\n password: z.string().optional(),\n /** 私钥文件路径(省略时使用 ssh-agent 或 ~/.ssh 默认密钥) */\n identityFile: z.string().min(1).optional(),\n /** known_hosts 文件路径(省略时使用默认;配合 CI/临时环境隔离主机指纹) */\n knownHostsFile: z.string().min(1).optional(),\n /** 严格主机密钥校验,默认开启(true→accept-new 首次信任并拒绝变更;false→关闭校验) */\n strictHostKeyChecking: z.boolean().default(true),\n /** 连接超时(秒) */\n connectTimeoutSeconds: z.number().int().positive().default(10),\n}).superRefine((ssh, context) => {\n // 未启用的旧密码不影响显式 key;空串不改变省略 auth 时的原有默认行为。\n if (ssh.auth === 'key' || (ssh.auth === undefined && !ssh.password))\n return\n if (!ssh.password || /[\\r\\n\\0]/.test(ssh.password) || new TextEncoder().encode(ssh.password).length > 1023)\n context.addIssue({ code: 'custom', path: ['password'], message: deployM('deploy_sshPasswordInvalid') })\n})\n\n/** 入口域名同时用于证书校验、Nginx 与公开 URL,禁止配置指令或路径。 */\nconst HttpsDomainSchema = z.string().max(253).regex(/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i).refine(value => !value.includes('..'))\nconst httpsOptions = {\n /** 公开访问域名;同时用于证书身份校验和 Nginx 入口。 */\n domain: HttpsDomainSchema.describe('HTTPS 公开域名;证书必须匹配该域名'),\n /** HTTPS 宿主端口,与 HTTP 端口不同。 */\n port: z.number().int().min(1).max(65535).default(443).describe('HTTPS 宿主端口,默认 443,须与 HTTP 端口不同'),\n /** 是否将普通 HTTP 请求跳转到 HTTPS。 */\n redirectHttp: z.boolean().default(true).describe('普通 HTTP 请求是否以 308 跳转至 HTTPS,健康检查和 ACME 挑战除外'),\n}\nconst HttpsConfigSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('files'),\n ...httpsOptions,\n /** 相对于工程根或绝对路径的 PEM 完整证书链及未加密私钥。 */\n certificateFile: z.string().min(1).describe('PEM 完整证书链路径,相对工程根或绝对路径;打包时复制到私有发布目录'),\n privateKeyFile: z.string().min(1).describe('未加密 PEM 私钥路径,相对工程根或绝对路径;必须与证书匹配'),\n }),\n z.object({\n type: z.literal('letsencrypt'),\n ...httpsOptions,\n domain: HttpsDomainSchema.refine(value => value.includes('.') && !/^\\d+(?:\\.\\d+){3}$/.test(value)).describe('Let’s Encrypt 单个公网域名,使用 HTTP-01,不支持 IP 或通配符'),\n email: z.email().describe('Let’s Encrypt 账号联系邮箱'),\n /** 使用者须明确同意 Let's Encrypt 的服务条款。 */\n acceptTerms: z.literal(true).describe('明确同意 Let’s Encrypt 服务条款后才可设置为 true'),\n }),\n])\n\n/** HTTP 端口及可选 HTTPS 入口;Let's Encrypt 使用 HTTP-01,HTTP 必须映射 80。 */\nconst PortExposeSchema = z.object({\n type: z.literal('port').default('port'),\n /** 容器内监听端口(adapter-node 默认 3000) */\n containerPort: z.number().int().min(1).max(65535).default(3000),\n /** 宿主机映射端口 */\n hostPort: z.number().int().min(1).max(65535),\n /** 可选 HTTPS:已有 PEM 文件或官方 Certbot 自动申请续期;省略保留 HTTP。 */\n https: HttpsConfigSchema.optional().describe('可选 HTTPS 入口;files 使用已有证书,letsencrypt 使用官方 Certbot 申请续期,省略保持 HTTP'),\n}).superRefine((expose, context) => {\n if (expose.https && (expose.https.port === expose.hostPort || (expose.https.type === 'letsencrypt' && expose.hostPort !== 80)))\n context.addIssue({ code: 'custom', path: ['https'], message: deployM('deploy_httpsPortsInvalid') })\n})\n\n/** 应用入口:HTTP 及统一的可选 HTTPS。 */\nconst ExposeSchema = PortExposeSchema\n\n/** docker-ssh 部署平台配置 */\nconst DockerSshProviderConfigSchema = z.object({\n type: z.literal('docker-ssh'),\n /** SSH 连接参数 */\n ssh: SshConfigSchema.optional(),\n /** 远程主机运行参数 */\n remote: z.object({\n /** 远程应用根目录 */\n baseDir: z.string().regex(/^\\/[\\w/. -]+$/).refine(value => !value.split('/').includes('..')).default('/opt/hai/apps'),\n /** 远程容器运行时(auto 优先 podman) */\n runtime: z.enum(['auto', 'docker', 'podman']).default('auto'),\n }).default({ baseDir: '/opt/hai/apps', runtime: 'auto' }),\n /** 应用暴露方式 */\n expose: ExposeSchema,\n /** Nginx 前方可信负载均衡的 IP/CIDR;省略时不接受外部转发头。 */\n trustedEdgeProxies: z.array(z.union([z.ipv4(), z.ipv6(), z.cidrv4(), z.cidrv6()])).max(1000).optional(),\n})\n\n/**\n * 部署平台配置联合类型(后续可扩展更多平台)\n * 按 type 区分 Vercel 与 docker-ssh;仅校验配置形状,不验证远端连通性或云凭据。\n * @example\n * ```ts\n * import { ProviderConfigSchema } from '@h-ai/deploy'\n * const result = ProviderConfigSchema.safeParse({ type: 'docker-ssh', expose: { hostPort: 8080 } })\n * if (!result.success) throw new Error('Invalid deployment provider')\n * const provider = result.data\n * ```\n */\nexport const ProviderConfigSchema = z.discriminatedUnion('type', [\n VercelProviderConfigSchema,\n DockerSshProviderConfigSchema,\n])\n\n/**\n * SSH 连接配置(parse 后)\n * 这是 Schema 解析后的类型,默认字段已必填;auth 省略时非空密码选择 password,否则使用 ssh-agent/默认密钥;显式 key 忽略残留 password。\n * @example\n * ```ts\n * import type { SshConfig } from '@h-ai/deploy'\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * ```\n */\nexport type SshConfig = z.infer<typeof SshConfigSchema>\n\n/**\n * 端口暴露配置(parse 后)\n * @example\n * ```ts\n * import type { PortExposeConfig } from '@h-ai/deploy'\n * const ports: PortExposeConfig = { type: 'port', hostPort: 8080, containerPort: 3000 }\n * ```\n */\nexport type PortExposeConfig = z.infer<typeof PortExposeSchema>\n\n/**\n * docker-ssh 部署平台配置(parse 后)\n * SSH 可省略用于离线打包;真正在线发布必须提供 SSH 配置。\n * @example\n * ```ts\n * import type { DockerSshProviderConfig } from '@h-ai/deploy'\n * const provider: DockerSshProviderConfig = { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } }\n * ```\n */\nexport type DockerSshProviderConfig = z.infer<typeof DockerSshProviderConfigSchema>\n\n// ─── Provisioner 配置 Schema ───\n\n/** Neon PostgreSQL 服务配置 */\nconst NeonServiceSchema = z.object({\n provisioner: z.literal('neon'),\n apiKey: z.string().min(1),\n})\n\n/** Upstash Redis 服务配置 */\nconst UpstashServiceSchema = z.object({\n provisioner: z.literal('upstash'),\n email: z.string().email(),\n apiKey: z.string().min(1),\n})\n\n/** Cloudflare R2 存储服务配置 */\nconst R2ServiceSchema = z.object({\n provisioner: z.literal('cloudflare-r2'),\n accessKeyId: z.string().min(1),\n secretAccessKey: z.string().min(1),\n accountId: z.string().min(1),\n apiToken: z.string().min(1),\n})\n\n/** Resend 邮件服务配置 */\nconst ResendServiceSchema = z.object({\n provisioner: z.literal('resend'),\n from: z.string().email(),\n apiKey: z.string().min(1),\n})\n\n/** 阿里云短信服务配置 */\nconst AliyunSmsServiceSchema = z.object({\n provisioner: z.literal('aliyun'),\n signName: z.string().min(1),\n accessKeyId: z.string().min(1),\n accessKeySecret: z.string().min(1),\n})\n\n/** 基础设施服务配置 */\nconst ServicesConfigSchema = z.object({\n db: z.discriminatedUnion('provisioner', [NeonServiceSchema]).optional(),\n cache: z.discriminatedUnion('provisioner', [UpstashServiceSchema]).optional(),\n storage: z.discriminatedUnion('provisioner', [R2ServiceSchema]).optional(),\n email: z.discriminatedUnion('provisioner', [ResendServiceSchema]).optional(),\n sms: z.discriminatedUnion('provisioner', [AliyunSmsServiceSchema]).optional(),\n}).optional()\n\n// ─── 完整配置 Schema ───\n\n/**\n * 部署模块完整配置 Schema\n * @example\n * ```ts\n * import { DeployConfigSchema } from '@h-ai/deploy'\n * const parsed = DeployConfigSchema.safeParse({ environment: 'prod', provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!parsed.success) throw new Error('Invalid deployment configuration')\n * const baseDir = parsed.data.provider.type === 'docker-ssh' ? parsed.data.provider.remote.baseDir : undefined\n * ```\n */\nexport const DeployConfigSchema = z.object({\n /** 部署环境文件模式;dev/test/prod 或自定义模式,禁止 local/example。 */\n environment: z.string().regex(/^[a-z0-9][\\w-]*$/i).refine(value => !['local', 'example'].includes(value.toLowerCase())).optional(),\n provider: ProviderConfigSchema,\n services: ServicesConfigSchema,\n /** Docker Compose 部署参数;构建配置位于项目 hai.json.build。 */\n container: z.object({\n /** 自建 S3 服务实现;协议仍为 storage.type=s3。 */\n s3Engine: z.enum(['rustfs', 'minio']).default('rustfs'),\n }).optional(),\n})\n\n/**\n * 部署配置类型(parse 后)\n * @example\n * ```ts\n * import type { DeployConfig } from '@h-ai/deploy'\n * const config: DeployConfig = { environment: 'prod', provider: { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } } }\n * ```\n */\nexport type DeployConfig = z.infer<typeof DeployConfigSchema>\n\n/**\n * 部署配置输入类型(用户输入)\n * @example\n * ```ts\n * import type { DeployConfigInput } from '@h-ai/deploy'\n * const input: DeployConfigInput = { provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } } // 由 init 应用 remote 等默认值。\n * ```\n */\nexport type DeployConfigInput = z.input<typeof DeployConfigSchema>\n","/**\n * @h-ai/deploy — 类型定义\n *\n * 本文件定义部署模块的核心接口和类型(非配置相关)。 配置相关类型请从 deploy-config.ts 导入。\n * @module deploy-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { DeployConfig, DeployConfigInput } from './deploy-config.js'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\nconst DeployErrorInfo = {\n DEPLOY_FAILED: '001:500',\n PROJECT_CREATE_FAILED: '002:500',\n UPLOAD_FAILED: '004:500',\n AUTH_REQUIRED: '005:401',\n AUTH_FAILED: '006:401',\n PROVISION_FAILED: '007:500',\n ADAPTER_MISSING: '008:500',\n SCAN_FAILED: '009:500',\n NOT_INITIALIZED: '010:500',\n ENV_VAR_FAILED: '011:500',\n UNSUPPORTED_TYPE: '012:400',\n CONFIG_ERROR: '013:500',\n CREDENTIAL_ERROR: '014:500',\n REMOTE_CONNECT_FAILED: '017:500',\n REMOTE_COMMAND_FAILED: '018:500',\n IMAGE_TRANSFER_FAILED: '019:500',\n HEALTH_CHECK_FAILED: '020:500',\n} as const satisfies ErrorInfo\n\n/**\n *\n * @example\n * ```ts\n * import { err } from '@h-ai/core'\n * import { HaiDeployError } from '@h-ai/deploy'\n * const result = err(HaiDeployError.CONFIG_ERROR, 'Invalid deployment configuration')\n * if (!result.success && result.error.code === HaiDeployError.CONFIG_ERROR.code) {\n * process.stderr.write(result.error.message + '\\n')\n * }\n * ```\n */\nexport const HaiDeployError = core.error.buildHaiErrorsDef('deploy', DeployErrorInfo)\n\n/**\n * 部署错误接口\n *\n * 用于组合错误定义、消息与可选 cause 的描述对象;业务操作返回的 error 遵循 core.HaiError,请按 success 分支读取 code/message。\n * @example\n * ```ts\n * import type { DeployError } from '@h-ai/deploy'\n * import { HaiDeployError } from '@h-ai/deploy'\n * const detail: DeployError = { def: HaiDeployError.DEPLOY_FAILED, message: 'Deployment failed' }\n * ```\n */\nexport interface DeployError {\n /** 错误定义 */\n def: (typeof HaiDeployError)[keyof typeof HaiDeployError]\n /** 错误消息 */\n message: string\n /** 原始错误(可选) */\n cause?: unknown\n}\n\n// ─── 服务类型 ───\n\n/**\n * 基础设施服务类型\n * @example\n * ```ts\n * import type { ServiceType } from '@h-ai/deploy'\n * const service: ServiceType = 'db'\n * ```\n */\nexport type ServiceType = 'db' | 'cache' | 'storage' | 'email' | 'sms' | 'vecdb' | 'ldap'\n\n/**\n * 每项中间件的处理方式;keep 不修改配置,也不开通服务。\n * @example\n * ```ts\n * import type { MiddlewareMode } from '@h-ai/deploy'\n * const mode: MiddlewareMode = 'keep' // 复用已有服务,不修改连接配置或自动开通。\n * ```\n */\nexport type MiddlewareMode = 'default' | 'custom' | 'keep'\n\n/**\n * 扫描环境;例如 `{ environment: 'test', envDir: '/workspace/app' }`。\n * @example\n * ```ts\n * import type { DeployScanOptions } from '@h-ai/deploy'\n * const options: DeployScanOptions = { environment: 'prod', envDir: '/workspace/shop' }\n * ```\n */\nexport interface DeployScanOptions {\n /** 环境文件模式。 */\n environment?: string\n /** 环境文件目录;默认自动定位到应用或 workspace 根。 */\n envDir?: string\n}\n\n/**\n * 依赖对应的中间件;例如 IAM 的 LDAP 位于 `iam.ldap`,可处于 disabled 状态。\n * @example\n * ```ts\n * import type { MiddlewareRequirement } from '@h-ai/deploy'\n * const requirement: MiddlewareRequirement = { service: 'db', backend: 'postgresql', source: '@h-ai/reldb', configName: 'db', configPath: [], envPrefix: 'HAI_DB', config: { host: 'db', database: 'shop' } }\n * // config 可能含私有值;展示时只选择安全字段。\n * ```\n */\nexport interface MiddlewareRequirement {\n /** 中间件类别。 */\n service: ServiceType\n /** 生效后端标识。 */\n backend: string\n /** 检测来源(依赖包或配置名),用于解释为何需要此项。 */\n source: string\n /** 模块配置名。 */\n configName: string\n /** 模块配置内的路径;例如 LDAP 为 ['ldap']。 */\n configPath: string[]\n /** 约定变量前缀。 */\n envPrefix: string\n /** 生效连接配置,可能含凭据,仅用于输入默认值,不得原样输出日志。 */\n config: Record<string, unknown>\n}\n\n// ─── 扫描结果 ───\n\n/**\n * 应用扫描结果\n *\n * 由 scanner 分析应用目录后返回,描述应用的框架类型、依赖和部署需求。\n * 扫描是文件系统能力,不依赖 init,也不代表远程服务已经连通。\n * @example\n * ```ts\n * import type { ScanResult } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const result = await deploy.scan(process.cwd(), { environment: 'prod' })\n * if (!result.success) throw new Error(result.error.message)\n * const scan: ScanResult = result.data\n * const services = scan.requiredServices\n * ```\n */\nexport interface ScanResult {\n /** 调用者指定的部署目录,对应 lockfile 中的一个 importer。 */\n appDir?: string\n /** 公共环境文件目录。 */\n envDir?: string\n /** 依赖与配置共同确定的中间件详情。 */\n middlewares?: MiddlewareRequirement[]\n /** 从运行依赖图识别的 Hai 模块;peer 和开发依赖不启用模块。 */\n haiModules?: string[]\n /** 工程名称(工程根 package.json.name;缺失时报错)。 */\n appName: string\n /** 是否为 SvelteKit 项目 */\n isSvelteKit: boolean\n /** 目标平台 adapter 是否已安装(如 @sveltejs/adapter-vercel) */\n adapterInstalled: boolean\n /** 容器部署所需的 @sveltejs/adapter-node 是否已安装 */\n nodeAdapterInstalled: boolean\n /** 检测到的模块依赖需要的服务列表 */\n requiredServices: ServiceType[]\n /** 各服务检测到的后端类型(如 db→postgresql/mysql,vecdb→qdrant),用于生成匹配的 sidecar */\n serviceBackends: Partial<Record<ServiceType, string>>\n}\n\n// ─── 部署结果 ───\n\n/**\n * 部署结果\n *\n * 包含部署后的访问 URL、状态和已设置的环境变量。\n * @example\n * ```ts\n * import type { DeployResult } from '@h-ai/deploy'\n * const packaged: DeployResult = { url: '', deploymentId: 'deploy-shop-001', status: 'packaged', bundlePath: '/workspace/shop/.hai/deploy/shop-1.0.0.tar', envVarsSet: [], provider: 'docker-ssh', healthCheck: 'skipped' }\n * // packaged 只代表交付包生成;不将其展示为服务已上线。\n * ```\n */\nexport interface DeployResult {\n /** 部署后的访问 URL */\n url: string\n /** 部署 ID */\n deploymentId: string\n /** 部署状态 */\n status: 'ready' | 'packaged' | 'building' | 'error'\n /** Compose 部署 tar 的绝对路径;包含私有配置,应安全传输。 */\n bundlePath?: string\n /** 手工搬运和启动说明;仅打包不代表服务器已运行。 */\n instructions?: string\n /** 已设置的环境变量名列表 */\n envVarsSet: string[]\n /** 部署 Provider 名称(如 vercel / docker-ssh),容器部署时返回 */\n provider?: string\n /** 健康检查结果:passed 表示 HTTP 探测成功,container-only 表示仅确认容器运行 */\n healthCheck?: 'passed' | 'container-only' | 'skipped'\n}\n\n// ─── 开通结果 ───\n\n/**\n * 基础设施开通结果\n *\n * 由 Provisioner 开通服务后返回,包含要注入到部署平台的环境变量。\n * @example\n * ```ts\n * import type { ProvisionResult } from '@h-ai/deploy'\n * const reused: ProvisionResult = { resourceStatus: 'reused', serviceType: 'db', provisionerName: 'neon', envVars: { HAI_DB_TYPE: 'postgresql' }, resourceInfo: 'Existing shop database' }\n * // envVars 可能含密码;不能直接输出。\n * ```\n */\nexport interface ProvisionResult {\n /** 本次新建或复用;凭证型服务始终为 reused */\n resourceStatus: 'created' | 'reused'\n /** 服务类型 */\n serviceType: ServiceType\n /** Provisioner 名称 */\n provisionerName: string\n /** 要注入到部署平台的环境变量 */\n envVars: Record<string, string>\n /** 资源标识信息(如项目名、数据库名等),用于日志和展示 */\n resourceInfo: string\n}\n\n/**\n * 部署失败后的安全恢复信息,不含环境变量值或原始异常。\n * @example\n * ```ts\n * import type { DeployRecoveryInfo } from '@h-ai/deploy'\n * const recovery: DeployRecoveryInfo = { projectName: 'shop', stage: 'provision', resources: [{ serviceType: 'db', provisionerName: 'neon', resourceInfo: 'shop', resourceStatus: 'unknown' }] }\n * // 先在供应商控制台核对 unknown 资源;避免重复创建计费资源。\n * ```\n */\nexport interface DeployRecoveryInfo {\n projectName: string\n stage: string\n platformProjectId?: string\n resources: Array<{\n serviceType: ServiceType\n provisionerName: string\n resourceInfo: string\n resourceStatus: 'created' | 'reused' | 'unknown'\n }>\n}\n\n/**\n * 命令失败后的已核验执行状态;远端 finished 仅指部署脚本及恢复已完成,不代表容器停止。\n * @example\n * ```ts\n * import type { DeployCommandState } from '@h-ai/deploy'\n * const state: DeployCommandState = { reason: 'timeout', localTermination: 'confirmed', remoteExecution: 'unknown', deploymentId: 'deploy-shop-001', resultFile: '/opt/hai/apps/shop/results/deploy-shop-001' }\n * if (state.remoteExecution === 'unknown') process.stderr.write('Verify the matching remote deployment result before retrying\\n')\n * ```\n */\nexport interface DeployCommandState {\n /** 失败触发原因。 */\n reason: 'timeout' | 'output' | 'input' | 'spawn' | 'exit' | 'configuration'\n /** 本地受管理树已全部退出、无法证明,或尚未启动。 */\n localTermination: 'confirmed' | 'unknown' | 'not-started'\n /** SSH 失败默认 unknown;读取匹配部署 ID 的完整终态结果后才为 finished。 */\n remoteExecution?: 'unknown' | 'finished'\n /** 本次不可变部署 ID,可与服务器结果核对。 */\n deploymentId?: string\n /** 服务器端结果文件;无凭据。 */\n resultFile?: string\n /** 匹配终态结果中的真实脚本退出码。 */\n remoteExitCode?: number\n /** 匹配终态结果中的最后阶段。 */\n remoteStage?: string\n /** 匹配终态中的恢复结果;passed 表示旧服务和 HTTP 验证通过,不包含业务数据回退。 */\n remoteRecovery?: 'not-needed' | 'passed' | 'failed' | 'stopped'\n}\n\n// ─── 部署选项 ───\n\n/**\n * 部署选项\n * 仅更新指定服务时仍受完整/部分制品与首次部署约束;bundleOnly 不触发 SSH。\n * @example\n * ```ts\n * import type { DeployAppOptions } from '@h-ai/deploy'\n * const options: DeployAppOptions = { environment: 'prod', bundleOnly: true, artifactDir: '.hai/build/docker/build-id', selectedServices: ['serv'], output: '.hai/deploy/shop.tar' }\n * ```\n */\nexport interface DeployAppOptions {\n /** 接收实际执行阶段,用于终端进度显示;不包含凭据或配置原文。 */\n onProgress?: (stage: 'packaging' | 'preflight' | 'images' | 'dependencies' | 'start' | 'https' | 'health' | 'complete') => void\n /** 只更新指定的 Compose 服务;省略时完整制品部署全部,部分制品只部署其镜像。 */\n selectedServices?: string[]\n /** 打包中间件镜像所用的本地引擎,auto 优先 Podman。 */\n runtime?: 'auto' | 'podman' | 'docker'\n /** 部署环境标识;显式指定时必须存在 .env.<environment>。 */\n environment?: string\n /** 环境文件所在目录,默认自动定位。 */\n envDir?: string\n /** 按服务或变量前缀选择处理方式;如 HAI_REACH_PROVIDERS_1 可独立于另一邮件连接。 */\n serviceModes?: Partial<Record<string, MiddlewareMode>>\n /** 是否跳过全部中间件配置与开通,默认 false;例如配置完备时设为 true。 */\n skipMiddleware?: boolean\n /** 已构建镜像目录;默认最近构建入口/锁文件目录下的 .hai/build/docker。 */\n artifactDir?: string\n /** 只生成独立交付目录(含 tar 和部署脚本),不连接 SSH;仅 docker-ssh 支持。 */\n bundleOnly?: boolean\n /** 交付包命名路径;默认在 .hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/ 中输出同名 tar 和脚本,自定义 release.tar 输出 release-<版本>/release-<版本>.tar;已有目录拒绝覆盖。 */\n output?: string\n}\n\n// ─── 凭证子功能 ───\n\n/**\n * Deploy 凭证文件操作。\n *\n * 这些方法仅操作 `~/.hai/credentials.yml`,不依赖 `deploy.init()`。\n * @example\n * ```ts\n * import type { DeployCredentialOperations } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const credentials: DeployCredentialOperations = deploy.credentials\n * const path = credentials.getPath() // 无需先 init。\n * ```\n */\nexport interface DeployCredentialOperations {\n /**\n * 获取凭证文件绝对路径。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const path = deploy.credentials.getPath() // 当前用户的全局凭证文件。\n * ```\n */\n getPath: () => string\n /**\n * 加载凭证文件并补齐 `process.env` 缺项;已有同名或父配置优先,返回文件中可识别的键名。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const loaded = deploy.credentials.load()\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const names = loaded.data // 不输出被注入的值。\n * ```\n */\n load: () => HaiResult<string[]>\n /**\n * 保存单个凭证。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = deploy.credentials.save('HAI_DEPLOY_PROVIDER_TOKEN', token)\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\n save: (key: string, value: string) => HaiResult<void>\n /**\n * 批量保存凭证。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = deploy.credentials.saveAll({ HAI_DEPLOY_PROVIDER_TOKEN: token })\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\n saveAll: (entries: Record<string, string>) => HaiResult<void>\n}\n\n// ─── 模块功能接口 ───\n\n/**\n * Deploy 模块功能接口\n *\n * 提供自动化部署的完整 API:\n * - `deploy.credentials.*()` — 凭证文件读写(不依赖 init)\n * - `deploy.init()` — 初始化(加载配置、创建 Provider 和 Provisioner)\n * - `deploy.scan()` — 扫描应用依赖(纯文件系统能力,不依赖 init)\n * - `deploy.provisionAll()` — 开通所有已配置的基础设施\n * - `deploy.deployApp()` — 完整部署流程\n * - `deploy.close()` — 关闭模块\n * scan 与 credentials 不需要 init;部署与开通遵循 init → 检查结果 → use → finally close。close 返回 Promise<void>,不伪造 HaiResult。\n * @example\n * ```ts\n * import type { DeployFunctions } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const operations: DeployFunctions = deploy\n * const scan = await operations.scan(process.cwd())\n * if (!scan.success) throw new Error(scan.error.message)\n * const required = scan.data.requiredServices\n * ```\n */\nexport interface DeployFunctions {\n /** 全局部署凭证文件操作。 */\n readonly credentials: DeployCredentialOperations\n /**\n * 初始化模块(加载配置、创建 Provider 和 Provisioner 实例)\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * const ready = deploy.isInitialized\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n init: (config: DeployConfigInput) => Promise<HaiResult<void>>\n /**\n * 关闭模块\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * const provider = deploy.config?.provider.type\n * }\n * finally {\n * await deploy.close() // Promise<void>;不检查不存在的 success 字段。\n * }\n * ```\n */\n close: () => Promise<void>\n /** 当前配置 */\n readonly config: DeployConfig | null\n /** 是否已初始化 */\n readonly isInitialized: boolean\n\n /**\n * 扫描应用目录,检测依赖和所需服务。\n *\n * 这是纯文件系统分析能力,不依赖云端认证状态,可在 `deploy.init()` 之前调用。\n *\n * @param appDir - 应用根目录路径\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const scanned = await deploy.scan(process.cwd(), { environment: 'prod' })\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const services = scanned.data.requiredServices // 无需 init。\n * ```\n */\n scan: (appDir: string, options?: DeployScanOptions) => Promise<HaiResult<ScanResult>>\n\n /**\n * 对所有已配置的 Provisioner 执行基础设施开通\n *\n * @param projectName - 用于资源命名的项目名\n * @returns 所有 Provisioner 的结果列表\n * @example\n * ```ts\n * import { deploy, getDeployRecovery } from '@h-ai/deploy'\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_DB_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_DB_APIKEY privately')\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } }, services: { db: { provisioner: 'neon', apiKey } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 会访问真实云服务并可能新建资源。\n * const result = await deploy.provisionAll('shop', ['db'])\n * if (!result.success) {\n * const recovery = getDeployRecovery(result.error)\n * if (recovery?.resources.some(resource => resource.resourceStatus === 'unknown')) {\n * process.stderr.write('Verify unknown resources at the provider before retrying\\n')\n * }\n * throw new Error(result.error.message)\n * }\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n provisionAll: (projectName: string, services?: ServiceType[]) => Promise<HaiResult<ProvisionResult[]>>\n\n /**\n * 部署已有构建产物(环境和中间件 → 打包 → 上传/启动);不会调用构建命令。\n *\n * @param appDir - 应用根目录路径\n * @param options - 部署选项\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 当前项目必须已有构建镜像清单与生产环境配置。\n * const result = await deploy.deployApp(process.cwd(), { environment: 'prod', bundleOnly: true })\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.status // packaged 不代表线上运行。\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n deployApp: (appDir: string, options?: DeployAppOptions) => Promise<HaiResult<DeployResult>>\n}\n","/** 部署环境的加载和持久化;公开环境文件不保存真实凭据。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { chmodSync, existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { extname, join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { parseEnv } from 'node:util'\nimport { core, err, ok } from '@h-ai/core'\nimport { LineCounter, parse, parseDocument } from 'yaml'\nimport { ProviderConfigSchema } from './deploy-config.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\n/**\n * 部署环境快照;例如 prod 的 targetValues 只来自 `.env.prod`,不包含基础/私有覆盖。\n * @example\n * ```ts\n * import type { DeploymentEnvironment } from '@h-ai/deploy'\n * const environment: DeploymentEnvironment = { environment: 'prod', envDir: '/workspace/shop', values: { HAI_DB_TYPE: 'postgresql' }, targetValues: { HAI_DB_TYPE: 'postgresql' } }\n * // values 可能还含私有凭据,不能整体写入日志。\n * ```\n */\nexport interface DeploymentEnvironment {\n /** 文件模式(dev/test/prod 或其他合法模式名)。 */\n environment: string\n /** 环境文件的绝对目录。 */\n envDir: string\n /** 合并后的部署变量,可能含私有值,不得直接记录日志。 */\n values: Record<string, string>\n /** 仅目标环境文件显式声明的变量,用于判断能否“保持不变”。 */\n targetValues: Record<string, string>\n}\n\n/** 与 Core 一致,普通字符串如 CORS 的 `*` 不能因 YAML 标量解析失败而使配置加载失败。 */\nfunction environmentValue(value: string): unknown {\n try {\n return parse(value) ?? value\n }\n catch {\n return value\n }\n}\n\nconst SSH_PREFIX = 'HAI_DEPLOY_PROVIDER_SSH'\nconst sshProvider = ProviderConfigSchema.options.find(provider => 'ssh' in provider.shape)\n// 从同一 Schema 读取已知键;不把任意环境变量扩成配置字段。\nconst sshFields = new Map(sshProvider && 'ssh' in sshProvider.shape\n ? Object.keys(sshProvider.shape.ssh.unwrap().shape).map(name => [name.toUpperCase(), name])\n : [])\nconst numericSshFields = new Set(['PORT', 'CONNECTTIMEOUTSECONDS', 'STRICTHOSTKEYCHECKING'])\n\n/** 在已解析的结构上覆盖;部署父对象仍允许同来源、更具体的 SSH 字段覆盖。 */\nfunction resolveConfig(value: unknown, prefix: string, env: Record<string, string | undefined>, deployment = false, literal = false): unknown {\n const sshField = prefix.startsWith(`${SSH_PREFIX}_`) ? prefix.slice(SSH_PREFIX.length + 1) : undefined\n const textSshField = sshField !== undefined && sshFields.has(sshField) && !numericSshFields.has(sshField)\n if (env[prefix] !== undefined) {\n if (deployment && textSshField)\n return env[prefix]\n if (!deployment)\n return environmentValue(env[prefix])\n value = environmentValue(env[prefix])\n // 环境 JSON 中的密码等文本已经是字面量,不能二次展开其中的 ${...}。\n literal = true\n }\n if (Array.isArray(value))\n return value.map((item, index) => resolveConfig(item, `${prefix}_${index}`, env, deployment, literal))\n if (value && typeof value === 'object') {\n const input: Record<string, unknown> = { ...value }\n if (deployment) {\n const hasSshInput = env[SSH_PREFIX] !== undefined || [...sshFields.keys()].some(field => env[`${SSH_PREFIX}_${field}`] !== undefined)\n if (hasSshInput && prefix === 'HAI_DEPLOY' && input.provider === undefined)\n input.provider = {}\n if (hasSshInput && prefix === 'HAI_DEPLOY_PROVIDER' && input.ssh === undefined)\n input.ssh = {}\n if (prefix === SSH_PREFIX) {\n for (const [field, name] of sshFields) {\n if (env[`${SSH_PREFIX}_${field}`] !== undefined && !(name in input))\n input[name] = undefined\n }\n }\n }\n return Object.fromEntries(Object.entries(input).map(([key, nested]) => [key, resolveConfig(nested, `${prefix}_${key.toUpperCase()}`, env, deployment, literal)]))\n }\n if (typeof value !== 'string')\n return value\n if (literal)\n return value\n const resolved = value.replace(/\\$\\{([^:}]+)(?::([^}]*))?\\}/g, (_match, name: string, fallback?: string) => env[name] ?? fallback ?? '')\n return /^\\$\\{[^}]+\\}$/.test(value) && !textSshField ? environmentValue(resolved) : resolved\n}\n\n/** 读取单层 dotenv;所有错误由调用边界转换为脱敏 HaiResult。 */\nfunction environmentFile(path: string): Record<string, string> {\n const values: Record<string, string> = {}\n if (existsSync(path)) {\n for (const [name, value] of Object.entries(parseEnv(readFileSync(path, 'utf8')))) {\n if (value !== undefined)\n values[name] = value\n }\n }\n return values\n}\n\n/**\n * 按来源归并环境变量;HAI 高层父配置清除旧叶,同层按父→叶处理。\n * @param layers - 从低到高优先级的环境来源。\n * @param prefix - 可选变量前缀,仅归并该模块。\n * @returns 归并后的字面量环境变量,可能包含秘密。\n * @example 模块内部上下文\n * ```ts\n * const env = mergeEnvironmentLayers([{ HAI_CACHE_TYPE: 'memory' }, { HAI_CACHE: '{\"type\":\"redis\"}' }])\n * ```\n */\nexport function mergeEnvironmentLayers(layers: Array<Record<string, string | undefined>>, prefix?: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const layer of layers) {\n const names = Object.keys(layer).filter(name => !prefix || name === prefix || name.startsWith(`${prefix}_`)).sort((left, right) => left.length - right.length)\n for (const name of names) {\n const value = layer[name]\n if (value === undefined)\n continue\n if (name.startsWith('HAI_')) {\n for (const previous of Object.keys(result)) {\n if (previous.startsWith(`${name}_`))\n delete result[previous]\n }\n }\n result[name] = value\n }\n }\n return result\n}\n\n/**\n * 按部署环境解析配置;未选择的可选 Provisioner 缺少凭据时保留空值,选择完成后由 Schema 校验。\n * hai.json 只读取对应的根分区;运行时模块继续读取 YAML。不修改 core 缓存或进程变量。\n * @param name - 模块配置名,例如 deploy/db/iam\n * @param path - hai.json 或运行时 YAML 文件的绝对路径\n * @param values - 已加载的目标环境变量\n * @returns 配置对象;解析错误已脱敏\n * @example\n * ```ts\n * import { loadDeploymentConfig, loadDeploymentEnvironment } from '@h-ai/deploy'\n * const environment = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!environment.success) throw new Error(environment.error.message)\n * const config = loadDeploymentConfig('deploy', `${process.cwd()}/hai.json`, environment.data.values)\n * if (!config.success) throw new Error(config.error.message)\n * // 返回对象仍需经 DeployConfigSchema 或 deploy.init 验证。\n * ```\n */\nexport function loadDeploymentConfig(name: string, path: string, values: Record<string, string | undefined>): HaiResult<Record<string, unknown>> {\n try {\n const content = readFileSync(path, 'utf8')\n let input: unknown\n if (extname(path).toLowerCase() === '.json') {\n try {\n const project: unknown = JSON.parse(content)\n input = project && typeof project === 'object' && !Array.isArray(project) ? (project as Record<string, unknown>)[name] : undefined\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n }\n if (!input || typeof input !== 'object' || Array.isArray(input))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n }\n else {\n const lineCounter = new LineCounter()\n const document = parseDocument(content, { lineCounter, prettyErrors: false })\n if (document.errors.length)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: String(lineCounter.linePos(document.errors[0]!.pos[0]).line) } }))\n input = document.toJS()\n }\n const config = resolveConfig(input, `HAI_${name.toUpperCase()}`, values, name === 'deploy')\n if (config !== null && (typeof config !== 'object' || Array.isArray(config)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n return ok(config && typeof config === 'object' && !Array.isArray(config) ? config as Record<string, unknown> : {})\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileUnreadable', { params: { path } }))\n }\n}\n\n/**\n * 加载部署环境;指定环境文件缺失时返回错误并要求用户创建。\n * 部署目标按进程 > 模式私有 > 模式公共 > 旧全局私有 > 基础归并。\n * 其它模块保留进程 > 模式私有 > 旧全局私有 > 模式公共 > 基础;targetValues 仅记录模式公共项。\n * @param options - 模式、环境目录与是否强制存在目标文件\n * @param options.environment - dev/test/prod 或自定义模式\n * @param options.envDir - 环境文件所在目录\n * @param options.requireFile - 默认 true;扫描无显式环境时可只读取已有基础文件\n * @returns 环境快照,可能包含私有值,不得直接输出\n * @example\n * ```ts\n * import { loadDeploymentEnvironment } from '@h-ai/deploy'\n * const loaded = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const explicitlyConfigured = loaded.data.targetValues.HAI_DB_TYPE\n * ```\n */\nexport function loadDeploymentEnvironment(options: { environment: string, envDir: string, requireFile?: boolean }): HaiResult<DeploymentEnvironment> {\n const environment = options.environment === 'production' ? 'prod' : options.environment === 'development' ? 'dev' : options.environment\n if (!/^[a-z0-9][\\w-]*$/i.test(environment) || ['local', 'example'].includes(environment.toLowerCase()))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_invalidEnvironment'))\n const envDir = resolve(options.envDir)\n const target = join(envDir, `.env.${environment}`)\n if (options.requireFile !== false && !existsSync(target))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_environmentMissing', { params: { path: target } }))\n const loaded = core.config.loadEnvFiles({ mode: environment, envDir })\n if (!loaded.success)\n return loaded\n try {\n const base = environmentFile(join(envDir, '.env'))\n const globalPrivate = environmentFile(join(envDir, '.env.local'))\n const selected = environmentFile(target)\n const modePrivate = environmentFile(join(envDir, `.env.${environment}.local`))\n const values = { ...loaded.data, ...modePrivate }\n // Core 已处理原三层;模式私有层也必须继续服从显式进程覆盖。\n for (const name of Object.keys(values)) {\n if (process.env[name] !== undefined)\n values[name] = process.env[name]\n }\n // 只传递应用配置和显式声明的运行变量,不上传整个调用者进程环境。\n for (const [name, value] of Object.entries(process.env)) {\n if (/^(?:HAI_|PUBLIC_|VITE_)/.test(name) && value !== undefined)\n values[name] = value\n }\n for (const name of Object.keys(values)) {\n if (name === 'HAI_DEPLOY' || name.startsWith('HAI_DEPLOY_'))\n delete values[name]\n }\n Object.assign(values, mergeEnvironmentLayers([base, globalPrivate, selected, modePrivate, process.env], 'HAI_DEPLOY'))\n values.HAI_DEPLOY_ENVIRONMENT = environment\n values.HAI_CORE_ENV ??= environment === 'prod' ? 'production' : environment === 'dev' ? 'development' : environment === 'test' ? 'test' : 'staging'\n return ok({ environment, envDir, values, targetValues: selected })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_environmentReadFailed'))\n }\n}\n\n/** 判断值是否包含凭据;连接 URL 和 JSON 配置需要递归检查。 */\nfunction isSecret(name: string, value: string): boolean {\n if (/PASSWORD|SECRET|TOKEN|APIKEY|PRIVATEKEY|ACCESSKEY|AUTHORIZATION/i.test(name.replace(/[^a-z0-9]/gi, '')) || /(?:^|_)PASS$/i.test(name) || value.includes('PRIVATE KEY'))\n return true\n try {\n const url = new URL(value)\n if (url.username || url.password || [...url.searchParams.keys()].some(key => /password|secret|token|key|authorization/i.test(key)))\n return true\n }\n catch { /* 非 URL 配置继续按结构检查。 */ }\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n return Object.entries(parsed).some(([key, nested]) => isSecret(key, typeof nested === 'string' ? nested : JSON.stringify(nested)))\n }\n catch { /* 普通字符串无需 JSON 处理。 */ }\n return false\n}\n\n/** 将 JSON 中的凭据剥离,公共文件仍保留可审查的后端/连接结构。 */\nfunction publicConfig(value: unknown): unknown {\n if (Array.isArray(value))\n return value.map(publicConfig)\n if (value && typeof value === 'object')\n return Object.fromEntries(Object.entries(value).filter(([name, item]) => !isSecret(name, typeof item === 'string' ? item : '')).map(([name, item]) => [name, publicConfig(item)]))\n return value\n}\n\n/** dotenv 引号保留空格、注释符、美元符号和 JSON;非法换行键由调用边界拒绝。 */\nfunction quoteEnv(value: string): string {\n // JSON 内用 Unicode 转义表示单引号,dotenv 单引号即可无损保存复杂密码。\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n return `'${JSON.stringify(parsed).replaceAll('\\'', '\\\\u0027')}'`\n }\n catch { /* 标量按 dotenv 原生引号规则处理。 */ }\n if (!value.includes('\\''))\n return `'${value}'`\n if (!value.includes('\"'))\n return `\"${value}\"`\n if (!value.includes('`'))\n return `\\`${value}\\``\n if (!/[\\r\\n#]/.test(value))\n return value\n throw new Error('Unsupported dotenv value')\n}\n\n/** 按原有行更新键,保留注释与其他配置;更新私有文件时要求权限 600。 */\nfunction updateFile(path: string, values: Record<string, string>, privateFile: boolean): void {\n let content = existsSync(path) ? readFileSync(path, 'utf8') : '# Local private deployment configuration; do not commit.\\n'\n for (const [name, value] of Object.entries(values)) {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name))\n throw new Error('Invalid environment variable name')\n const line = `${name}=${quoteEnv(value)}`\n // parseEnv 支持多行引号;替换时一起消费原值,避免遗留秘密片段。\n const pattern = new RegExp(`^(?:export\\\\s+)?${name}\\\\s*=\\\\s*(?:'[^']*'|\"[^\"]*\"|\\`[^\\`]*\\`|[^\\\\r\\\\n]*)[^\\\\r\\\\n]*`, 'gm')\n if (pattern.test(content))\n content = content.replace(pattern, () => line)\n else\n content = `${content.trimEnd()}\\n${line}\\n`\n }\n writeFileSync(path, content, { mode: privateFile ? 0o600 : 0o644 })\n if (privateFile)\n chmodSync(path, 0o600)\n}\n\n/** 明确修改的公共项必须清掉同名旧私有覆盖,避免重新加载后仍用旧后端。 */\nfunction removeOverrides(path: string, names: string[], privateFile = true): void {\n if (!existsSync(path) || names.length === 0)\n return\n let content = readFileSync(path, 'utf8')\n for (const name of names)\n content = content.replace(new RegExp(`^(?:export\\\\s+)?${name}\\\\s*=\\\\s*(?:'[^']*'|\"[^\"]*\"|\\`[^\\`]*\\`|[^\\\\r\\\\n]*)[^\\\\r\\\\n]*(?:\\\\r?\\\\n|$)`, 'gm'), '')\n writeFileSync(path, content, { mode: privateFile ? 0o600 : 0o644 })\n chmodSync(path, privateFile ? 0o600 : 0o644)\n}\n\n/**\n * 保存部署变量:公共值写目标环境文件,凭据写 `.env.<environment>.local`;旧共享私有文件不删除。\n * 返回实际写入的变量名,调用者只展示名称或脱敏值。\n * @param environment - 已加载的目标环境快照\n * @param values - 需要更新的变量;未提供的项保持原状\n * @param options - private 为 true 时所有值只保存在本机;适用于 SSH 地址、端口及密钥路径\n * @param options.private - 是否将全部值保存到选中模式的私有文件\n * @returns 已保存的变量名或脱敏错误\n * @example\n * ```ts\n * import { loadDeploymentEnvironment, saveDeploymentEnvironment } from '@h-ai/deploy'\n * const loaded = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const saved = saveDeploymentEnvironment(loaded.data, { HAI_DB_HOST: 'db' })\n * if (!saved.success) throw new Error(saved.error.message)\n * // 密钥应以 { private: true } 写入被忽略的 .env.prod.local,不能放公共环境文件。\n * ```\n */\nexport function saveDeploymentEnvironment(environment: DeploymentEnvironment, values: Record<string, string>, options: { private?: boolean } = {}): HaiResult<string[]> {\n try {\n const shared: Record<string, string> = {}\n const privateValues: Record<string, string> = {}\n for (const [name, value] of Object.entries(values)) {\n if (options.private) {\n privateValues[name] = value\n }\n else if (isSecret(name, value)) {\n privateValues[name] = value\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n shared[name] = JSON.stringify(publicConfig(parsed))\n }\n catch { /* 标量秘密仅写私有文件。 */ }\n }\n else {\n shared[name] = value\n }\n }\n const privatePath = join(environment.envDir, `.env.${environment.environment}.local`)\n const globalPrivate = environmentFile(join(environment.envDir, '.env.local'))\n // 非部署模块保留旧 private 优先级;显式换后端时在当前模式遮盖旧值,不破坏其它环境的 fallback。\n for (const [name, value] of Object.entries(shared)) {\n if (!(name in privateValues) && globalPrivate[name] !== undefined && name !== 'HAI_DEPLOY' && !name.startsWith('HAI_DEPLOY_'))\n privateValues[name] = value\n }\n if (Object.keys(shared).length)\n updateFile(join(environment.envDir, `.env.${environment.environment}`), shared, false)\n if (Object.keys(privateValues).length)\n updateFile(privatePath, privateValues, true)\n removeOverrides(join(environment.envDir, `.env.${environment.environment}`), Object.keys(privateValues).filter(name => !(name in shared)), false)\n removeOverrides(privatePath, Object.keys(shared).filter(name => !(name in privateValues)))\n if (Object.keys(privateValues).length) {\n const ignorePath = join(environment.envDir, '.gitignore')\n const ignore = existsSync(ignorePath) ? readFileSync(ignorePath, 'utf8') : ''\n const missing = ['.env.local', '.env.*.local', '.hai/deploy/'].filter(line => !ignore.split(/\\r?\\n/).includes(line))\n if (missing.length)\n writeFileSync(ignorePath, `${ignore.trimEnd()}\\n${missing.join('\\n')}\\n`)\n }\n return ok(Object.keys(values))\n }\n catch {\n return err(HaiDeployError.ENV_VAR_FAILED, deployM('deploy_environmentWriteFailed'))\n }\n}\n","/**\n * @h-ai/deploy — 部署辅助函数\n *\n * 包含已有产物目录解析等与部署流程相关的辅助操作。 从 deploy-main.ts 中提取,遵循 main 仅做生命周期管理的规范。\n * @module deploy-functions\n */\n\nimport type { DeployAppOptions, ScanResult, ServiceType } from './deploy-types.js'\nimport { existsSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { deployM } from './deploy-i18n.js'\n\n/**\n * 将工程根 package.json.name 归一化为镜像与部署资源共用的身份;移除 scope、转小写并合并非法字符。\n * @throws Error - 名称为空或归一化后不含字母数字。\n * @param name - 工程根 package.json.name。\n * @returns 可用于 OCI 镜像和 Compose 资源的工程名。\n * @example\n * ```ts\n * import { normalizeProjectName } from '@h-ai/deploy'\n * const name = normalizeProjectName('@shop/orders')\n * ```\n */\nexport function normalizeProjectName(name: string): string {\n const normalized = name.trim().replace(/^@[^/]+\\//, '').toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '')\n if (!normalized)\n throw new Error(deployM('deploy_projectNameRequired'))\n return normalized\n}\n\n/**\n * 定位工程根;API workspace 的环境文件可在服务包,构建与部署缓存仍位于工程根。\n * 只定位已约定的构建入口/锁文件,不从目录布局推断应用或中间件依赖。\n * 从目标包向上查找构建入口或锁文件;返回目录不表示清单已存在或通过校验。\n * @param appDir - 部署目标应用目录。\n * @returns 最近的工程入口目录;未找到入口时返回应用目录的绝对路径。\n * @example 模块内部上下文\n * ```ts\n * const project = resolveProjectDirectory('/workspace/shop/apps/shop-serv')\n * ```\n */\nexport function resolveProjectDirectory(appDir: string): string {\n let directory = resolve(appDir)\n while (true) {\n if (existsSync(join(directory, 'hai.json')) || existsSync(join(directory, 'pnpm-lock.yaml')))\n return directory\n const parent = dirname(directory)\n if (parent === directory)\n return resolve(appDir)\n directory = parent\n }\n}\n\n/**\n * 定位工程根的构建缓存目录;环境文件留在服务包时也沿用同一工程根。\n * @param appDir - 部署目标应用目录。\n * @returns 约定的 .hai/build/docker 目录;不保证其中制品存在或通过校验。\n * @example 模块内部上下文\n * ```ts\n * const directory = resolveArtifactDirectory('/workspace/shop/apps/shop-serv')\n * ```\n */\nexport function resolveArtifactDirectory(appDir: string): string {\n return join(resolveProjectDirectory(appDir), '.hai/build/docker')\n}\n\n/**\n * 判断同类连接中是否有默认配置项;具体变量前缀优先于服务类别,未指定时默认处理。\n * @param scan - 依据实际依赖图及环境得到的扫描结果。\n * @param service - 待判断的中间件类别。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 同类连接中存在采用 default 策略的项时为 true。\n * @example 模块内部上下文\n * ```ts\n * const scan: ScanResult = { appName: 'shop', isSvelteKit: false, adapterInstalled: false, nodeAdapterInstalled: false, requiredServices: [], serviceBackends: {} }\n * const enabled = usesDefaultMiddleware(scan, 'db', { serviceModes: { db: 'keep' } }) // false\n * ```\n */\nexport function usesDefaultMiddleware(scan: ScanResult, service: ServiceType, options?: DeployAppOptions): boolean {\n const requirements = scan.middlewares?.filter(item => item.service === service) ?? []\n return requirements.length\n ? requirements.some(item => (options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.[service] ?? 'default') === 'default')\n : (options?.serviceModes?.[service] ?? 'default') === 'default'\n}\n\n/**\n * 解析构建产物目录\n * @param appDir - 应用根目录\n * @param providerType - Provider 类型\n * @returns 产物目录路径\n * @example 模块内部上下文\n * ```ts\n * const directory = resolveOutputDir('/workspace/shop', 'vercel') // /workspace/shop/.vercel/output\n * ```\n */\nexport function resolveOutputDir(appDir: string, providerType: string): string {\n switch (providerType) {\n case 'vercel':\n return join(appDir, '.vercel', 'output')\n default:\n return join(appDir, 'build')\n }\n}\n","/**\n * @h-ai/deploy — 凭证管理\n *\n * 管理全局凭证文件 `~/.hai/credentials.yml`。\n * 这些 helper 由 `deploy.credentials.*` 对外暴露,供 CLI 在加载项目 `hai.json` 的部署配置\n * 之前注入 `HAI_DEPLOY_*` 环境变量。\n * @module deploy-credentials\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { core, err, ok } from '@h-ai/core'\nimport { parse, stringify } from 'yaml'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'credentials' })\n\n/** 仅允许写入 deploy 模块自有的环境变量前缀,避免把任意 YAML key 注入 process.env。 */\nconst DEPLOY_CREDENTIAL_KEY_PATTERN = /^HAI_DEPLOY_[A-Z0-9_]+$/\n\n// ─── 内部工具 ───\n\n/** 校验凭证键名是否属于 deploy 模块。 */\nfunction isAllowedCredentialKey(key: string): boolean {\n return DEPLOY_CREDENTIAL_KEY_PATTERN.test(key)\n}\n\n/**\n * 标准化凭证键值对。\n *\n * 仅保留 `HAI_DEPLOY_*` 键,且值必须是可安全序列化为字符串的标量。\n */\nfunction normalizeCredentialEntries(entries: Record<string, unknown>): Record<string, string> {\n const normalized: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(entries)) {\n if (!isAllowedCredentialKey(key)) {\n logger.warn('Ignoring unsupported deploy credential key', { key })\n continue\n }\n\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n normalized[key] = String(value)\n continue\n }\n\n logger.warn('Ignoring deploy credential with non-scalar value', { key })\n }\n\n return normalized\n}\n\n/** 在写入前校验单个凭证键名。 */\nfunction assertAllowedCredentialKey(key: string): void {\n if (!isAllowedCredentialKey(key)) {\n throw new Error(deployM('deploy_credentialInvalidKey', { params: { key } }))\n }\n}\n\n/** 在写入前校验批量凭证键名。 */\nfunction assertAllowedCredentialEntries(entries: Record<string, string>): void {\n for (const key of Object.keys(entries)) {\n assertAllowedCredentialKey(key)\n }\n}\n\n/**\n * 获取凭证文件路径\n * @returns `~/.hai/credentials.yml` 的绝对路径\n * @example 模块内部上下文\n * ```ts\n * const path = getCredentialsPath() // 当前用户 ~/.hai/credentials.yml,不含凭据内容。\n * ```\n */\nexport function getCredentialsPath(): string {\n return join(homedir(), '.hai', 'credentials.yml')\n}\n\n/**\n * 确保凭证目录存在\n *\n * @param filePath - 凭证文件路径\n */\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * 读取凭证文件内容\n *\n * @returns 解析后的键值对,文件不存在时返回空对象\n */\nfunction readCredentialsFile(): Record<string, string> {\n const filePath = getCredentialsPath()\n if (!existsSync(filePath)) {\n return {}\n }\n const content = readFileSync(filePath, 'utf-8')\n const parsed = parse(content)\n if (parsed === null || parsed === undefined || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return {}\n }\n return normalizeCredentialEntries(parsed as Record<string, unknown>)\n}\n\n/**\n * 写入凭证文件\n *\n * @param data - 凭证键值对\n */\nfunction writeCredentialsFile(data: Record<string, string>): void {\n const filePath = getCredentialsPath()\n ensureDir(filePath)\n const header = '# Managed by hai cli - do not edit manually\\n'\n const content = header + stringify(data)\n writeFileSync(filePath, content, { encoding: 'utf-8', mode: 0o600 })\n}\n\n// ─── 公共 API ───\n\n/**\n * 加载全局凭证文件并注入到 process.env\n *\n * 读取 `~/.hai/credentials.yml` 中的所有键值对,\n * 仅为尚未设置的键注入默认值;已有父配置也优先于全局文件的细分键,\n * 使后续 core 配置加载时自动解析 `${HAI_DEPLOY_*}` 变量。\n * @returns 返回文件中可识别的键名,包括被当前配置遮盖而未注入的键。\n * @example 模块内部上下文\n * ```ts\n * const loaded = loadCredentials()\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const credentialNames = loaded.data // 仅文件键名;已有 process.env 值优先。\n * ```\n */\nexport function loadCredentials(): HaiResult<string[]> {\n try {\n const data = readCredentialsFile()\n const keys = Object.keys(data)\n const configured = Object.keys(process.env).filter(key => (key === 'HAI_DEPLOY' || isAllowedCredentialKey(key)) && process.env[key] !== undefined)\n for (const key of keys) {\n if (!configured.some(name => key === name || key.startsWith(`${name}_`)))\n process.env[key] = String(data[key])\n }\n logger.debug('Credentials loaded', { count: keys.length })\n return ok(keys)\n }\n catch (error) {\n logger.error('Failed to load credentials', { error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n/**\n * 保存单个凭证到全局凭证文件\n *\n * 读取已有凭证 → 合并新凭证 → 写回文件。已有同名 key 会被覆盖。\n * 会写入当前用户的全局凭证文件;仅允许 HAI_DEPLOY_ 前缀。\n * @param key - 环境变量名(如 HAI_DEPLOY_PROVIDER_TOKEN)\n * @param value - 凭证值\n * @returns 已保存时成功;键名、文件或权限处理失败时为错误结果。\n * @example 模块内部上下文\n * ```ts\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = saveCredential('HAI_DEPLOY_PROVIDER_TOKEN', token)\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\nexport function saveCredential(key: string, value: string): HaiResult<void> {\n try {\n assertAllowedCredentialKey(key)\n const data = readCredentialsFile()\n data[key] = value\n writeCredentialsFile(data)\n process.env[key] = value\n logger.debug('Credential saved', { key })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Failed to save credential', { key, error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n/**\n * 批量保存凭证到全局凭证文件\n * @param entries - 凭证键值对\n * @returns 已保存时成功;校验失败不会注入任意键名。\n * @example 模块内部上下文\n * ```ts\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = saveCredentials({ HAI_DEPLOY_PROVIDER_TOKEN: token })\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\nexport function saveCredentials(entries: Record<string, string>): HaiResult<void> {\n try {\n assertAllowedCredentialEntries(entries)\n const data = readCredentialsFile()\n for (const [key, value] of Object.entries(entries)) {\n data[key] = value\n process.env[key] = value\n }\n writeCredentialsFile(data)\n logger.debug('Credentials saved', { count: Object.keys(entries).length })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Failed to save credentials', { error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n","/** 自建与云开通共用的配置合并;业务选项保留,连接选择器由实际开通结果定稿。 */\nimport type { MiddlewareRequirement, ServiceType } from './deploy-types.js'\n\n/** 旧地址、认证与连接模式不能覆盖新服务;其余同后端配置继续生效。 */\nconst connectionFields: Partial<Record<ServiceType, readonly string[]>> = {\n db: ['url', 'host', 'port', 'database', 'user', 'password', 'ssl'],\n cache: ['url', 'host', 'port', 'password', 'cluster', 'sentinel', 'tls'],\n storage: ['endpoint', 'bucket', 'region', 'accessKeyId', 'secretAccessKey', 'forcePathStyle', 'createBucket'],\n vecdb: ['url', 'host', 'port', 'database', 'user', 'password', 'apiKey', 'path', 'serverCommand', 'startupTimeout'],\n ldap: ['url', 'bindDn', 'bindPassword', 'searchBase', 'useTls'],\n email: ['host', 'port', 'secure', 'user', 'pass'],\n}\n\n/**\n * 将有效业务配置带入托管连接;切换后端时不迁移旧后端字段。\n * @param requirement - 扫描得到的最终有效中间件配置。\n * @param supplied - 自建或云开通生成的实际连接。\n * @returns 完整配置,可能含凭据,不能直接输出到日志。\n * @example 模块内部上下文\n * ```ts\n * const requirement: MiddlewareRequirement = { service: 'storage', backend: 's3', source: 'storage', configName: 'storage', configPath: [], envPrefix: 'HAI_STORAGE', config: { publicEndpoint: 'https://app.example.com/files' } }\n * const storage = mergeManagedMiddlewareConfig(requirement, { type: 's3', endpoint: 'http://storage:9000', bucket: 'hai' })\n * ```\n */\nexport function mergeManagedMiddlewareConfig(requirement: MiddlewareRequirement | undefined, supplied: Record<string, unknown>): Record<string, unknown> {\n if (!requirement || (requirement.service !== 'ldap' && requirement.backend !== supplied.type))\n return supplied\n const configured = { ...requirement.config }\n for (const field of connectionFields[requirement.service] ?? [])\n delete configured[field]\n const merged = { ...configured, ...supplied }\n // Redis URL 的数据库编号优先于独立 db 字段;保留选项时必须同步真实连接地址。\n if (requirement.service === 'cache' && typeof configured.db === 'number' && typeof supplied.url === 'string') {\n const url = new URL(supplied.url)\n if (configured.db !== 0 || (url.pathname !== '' && url.pathname !== '/')) {\n url.pathname = String(configured.db)\n merged.url = url.toString()\n }\n }\n return merged\n}\n","import type { HaiError, HaiResult } from '@h-ai/core'\nimport type { DeployCommandState, DeployRecoveryInfo } from './deploy-types.js'\nimport { err } from '@h-ai/core'\nimport { z } from 'zod'\nimport { deployM } from './deploy-i18n.js'\n\nconst RecoverySchema = z.object({\n projectName: z.string(),\n stage: z.string(),\n platformProjectId: z.string().optional(),\n resources: z.array(z.object({\n serviceType: z.enum(['db', 'cache', 'storage', 'email', 'sms']),\n provisionerName: z.string(),\n resourceInfo: z.string(),\n resourceStatus: z.enum(['created', 'reused', 'unknown']),\n })),\n})\n\nconst CommandStateSchema = z.object({\n reason: z.enum(['timeout', 'output', 'input', 'spawn', 'exit', 'configuration']),\n localTermination: z.enum(['confirmed', 'unknown', 'not-started']),\n remoteExecution: z.enum(['unknown', 'finished']).optional(),\n deploymentId: z.string().optional(),\n resultFile: z.string().optional(),\n remoteExitCode: z.number().int().optional(),\n remoteStage: z.string().optional(),\n remoteRecovery: z.enum(['not-needed', 'passed', 'failed', 'stopped']).optional(),\n})\n\n/**\n * 读取命令失败的安全状态;不把本地 SSH 退出解释为远端停止。\n * @param error - 部署错误\n * @returns 通过结构校验的命令状态,或 undefined\n * @example\n * ```ts\n * import { getDeployCommandState, HaiDeployError } from '@h-ai/deploy'\n * const state = getDeployCommandState({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: 'SSH connection interrupted', ext: { commandExecution: { reason: 'exit', localTermination: 'confirmed', remoteExecution: 'unknown' } } })\n * if (state?.remoteExecution === 'unknown') process.stderr.write('Remote execution is unknown\\n')\n * ```\n */\nexport function getDeployCommandState(error: HaiError): DeployCommandState | undefined {\n const parsed = CommandStateSchema.safeParse(error.ext?.commandExecution)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * 读取错误中的恢复清单;仅返回明确允许展示的字段。\n * @param error - 上层捕获的部署 HaiError;不直接展示其 cause。\n * @returns 安全恢复清单;结构不满足约定时为 undefined。\n * @example\n * ```ts\n * import { getDeployRecovery, HaiDeployError } from '@h-ai/deploy'\n * const recovery = getDeployRecovery({ ...HaiDeployError.PROVISION_FAILED, message: 'Provisioning failed', ext: { recovery: { projectName: 'shop', stage: 'provision', resources: [] } } })\n * if (recovery) {\n * const stage = recovery.stage\n * }\n * ```\n */\nexport function getDeployRecovery(error: HaiError): DeployRecoveryInfo | undefined {\n const parsed = RecoverySchema.safeParse(error.ext?.recovery)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * 在错误中保留可展示的恢复信息,避免异常 cause/命令/URL 泄漏凭证。\n * @param error - 上层捕获的部署 HaiError;不直接展示其 cause。\n * @param recovery - 允许展示的恢复阶段与资源清单。\n * @returns 仅含安全恢复字段的失败 HaiResult。\n * @example 模块内部上下文\n * ```ts\n * const { HaiDeployError } = await import('./deploy-types.js')\n * const failure = recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: 'Provisioning failed' }, { projectName: 'shop', stage: 'provision', resources: [] })\n * if (!failure.success) {\n * const safeMessage = failure.error.message\n * }\n * ```\n */\nexport function recoveryFailure(error: HaiError, recovery: DeployRecoveryInfo): HaiResult<never> {\n return err({\n code: error.code,\n httpStatus: error.httpStatus,\n system: error.system,\n module: error.module,\n message: deployM('deploy_recoveryFailure', { params: { stage: recovery.stage } }),\n suggestion: deployM('deploy_recoverySuggestion'),\n ext: { recovery },\n })\n}\n","/** 应用、环境文件与中间件依赖扫描;不依赖 deploy.init(),不修改进程环境。 */\nimport type { HaiResult } from '@h-ai/core'\nimport type { DeployScanOptions, MiddlewareRequirement, ScanResult, ServiceType } from './deploy-types.js'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { parseAllDocuments } from 'yaml'\nimport { loadDeploymentConfig, loadDeploymentEnvironment } from './deploy-environment.js'\nimport { resolveProjectDirectory } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'scanner' })\n\n/** 安全缩窄 YAML/JSON 对象;数组与 null 不作为配置对象。 */\nfunction record(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\n/**\n * 从当前 workspace 的 lockfile 导入项遍历运行依赖,排除 dev 和 peer 边。\n * pnpm 12 的工具链和应用分别存于多个 YAML 文档,只选择含目标 importer 的应用文档。\n * 缺少 lockfile 或目标 importer 时要求先安装,不读取 package.json 或推测应用布局。\n */\nfunction runtimeDependencies(appDir: string): { runtime: Set<string>, build: Set<string>, root: string } {\n let root = appDir\n while (!existsSync(join(root, 'pnpm-lock.yaml'))) {\n const parent = dirname(root)\n if (parent === root)\n throw new Error('Missing pnpm lockfile; run pnpm install')\n root = parent\n }\n const importerKey = relative(root, appDir).replaceAll('\\\\', '/') || '.'\n const documents = parseAllDocuments(readFileSync(join(root, 'pnpm-lock.yaml'), 'utf8'))\n if (documents.some(document => document.errors.length))\n throw new Error('Invalid pnpm lockfile')\n const lock = documents.map(document => record(document.toJS())).reverse().find(document => importerKey in record(document.importers))\n if (!lock)\n throw new Error('Application is missing from pnpm lockfile; run pnpm install')\n const importers = record(lock.importers)\n const packages = record(lock.packages)\n const snapshots = record(lock.snapshots)\n const names = new Set<string>()\n const visited = new Set<string>()\n const visit = (id: string, node: Record<string, unknown>, importer?: string): void => {\n if (visited.has(id))\n return\n visited.add(id)\n const metadata = importer === undefined ? record(packages[id.split('(')[0]]) : {}\n const peers = record(metadata.peerDependencies)\n for (const [name, reference] of Object.entries({ ...record(node.dependencies), ...record(node.optionalDependencies) })) {\n if (name in peers)\n continue\n const version = typeof reference === 'string' ? reference : record(reference).version\n if (typeof version !== 'string')\n throw new Error('Invalid pnpm dependency reference')\n if (version.startsWith('link:')) {\n if (importer === undefined)\n throw new Error('Invalid workspace dependency')\n const target = relative(root, resolve(root, importer, version.slice(5))).replaceAll('\\\\', '/') || '.'\n const linked = record(importers[target])\n if (!Object.keys(linked).length)\n throw new Error('Missing linked workspace importer')\n names.add(name)\n visit(`workspace:${target}`, linked, target)\n continue\n }\n // npm alias 的引用已包含真实包名,不能再拼接别名。\n const key = version in snapshots || version in packages ? version : `${name}@${version}`\n names.add(key.match(/^(@[^/]+\\/[^@]+|[^@]+)@/)?.[1] ?? name)\n const snapshot = record(snapshots[key] ?? packages[key])\n if (!Object.keys(snapshot).length && !(key in snapshots) && !(key in packages))\n throw new Error('Missing pnpm dependency snapshot')\n visit(key, snapshot)\n }\n }\n visit(`workspace:${importerKey}`, record(importers[importerKey]), importerKey)\n return { runtime: names, build: new Set([...names, ...Object.keys(record(record(importers[importerKey]).devDependencies))]), root }\n}\n\n/**\n * 扫描依赖和实际环境下的后端,不把 memory/local/console 强制改为外部服务。\n * 沿目标 importer 的运行依赖识别模块;LDAP 等可选能力再按实际配置识别。\n * 以真实运行依赖图和显式配置识别模块;缺少或不一致锁文件不能静默降级为猜测。\n * @param inputDir - 待扫描的真实应用包目录。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 实际应用、依赖与中间件需求,或失败 HaiResult。\n * @example 模块内部上下文\n * ```ts\n * const result = await scanApp(process.cwd(), { environment: 'prod' })\n * if (!result.success) throw new Error(result.error.message)\n * const enabled = result.data.haiModules\n * ```\n */\nexport async function scanApp(inputDir: string, options?: DeployScanOptions): Promise<HaiResult<ScanResult>> {\n try {\n const appDir = resolve(inputDir)\n const graph = runtimeDependencies(appDir)\n // 服务目录只决定依赖和配置;资源属于工程,不能把 -serv 等工作区后缀带入部署名。\n const projectDir = resolveProjectDirectory(appDir)\n const packageFile = join(projectDir, 'package.json')\n const project = existsSync(packageFile) ? record(JSON.parse(readFileSync(packageFile, 'utf8'))) : {}\n if (typeof project.name !== 'string' || !project.name.trim())\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameRequired'))\n const appName = project.name.trim()\n if (!appName.replace(/^@[^/]+\\//, '').replace(/[^a-z0-9]/gi, ''))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameRequired'))\n const envDir = options?.envDir ? resolve(options.envDir) : existsSync(join(appDir, '.env')) ? appDir : graph.root\n const loaded = loadDeploymentEnvironment({ environment: options?.environment ?? 'prod', envDir, requireFile: options?.environment !== undefined })\n if (!loaded.success)\n return loaded\n const env = loaded.data.values\n const deps = graph.runtime\n const configs: Record<string, Record<string, unknown>> = {}\n for (const [name, owner] of Object.entries({ db: 'reldb', cache: 'cache', storage: 'storage', vecdb: 'vecdb', iam: 'iam', reach: 'reach' })) {\n configs[name] = {}\n if (!deps.has(`@h-ai/${owner}`))\n continue\n const configFile = ['yml', 'yaml'].map(ext => join(appDir, 'config', `_${name}.${ext}`)).find(existsSync)\n const config = configFile ? loadDeploymentConfig(name, configFile, env) : undefined\n if (config && !config.success)\n return config\n configs[name] = config?.data ?? {}\n }\n const middlewares: MiddlewareRequirement[] = []\n const add = (service: ServiceType, backend: string, configName = service as string, configPath: string[] = [], config = configs[configName] ?? {}, source = `_${configName}.yml`) => {\n middlewares.push({ service, backend, source, configName, configPath, envPrefix: ['HAI', configName, ...configPath].map(part => part.toUpperCase()).join('_'), config })\n }\n const iam = deps.has('@h-ai/iam')\n if (deps.has('@h-ai/reldb'))\n add('db', String(configs.db.type ?? 'sqlite'), 'db', [], configs.db, '@h-ai/reldb / _db.yml')\n if (deps.has('@h-ai/cache'))\n add('cache', String(configs.cache.type ?? 'memory'), 'cache', [], configs.cache, '@h-ai/cache / _cache.yml')\n if (deps.has('@h-ai/storage'))\n add('storage', String(configs.storage.type ?? 'local'))\n if (deps.has('@h-ai/vecdb'))\n add('vecdb', String(configs.vecdb.type ?? 'lancedb'))\n if (iam) {\n const ldap = record(configs.iam.ldap)\n add('ldap', record(configs.iam.login).ldap === true ? 'ldap' : 'disabled', 'iam', ['ldap'], ldap, '@h-ai/iam (LDAP)')\n }\n const providers = configs.reach.providers\n if (deps.has('@h-ai/reach') && Array.isArray(providers)) {\n for (const [index, item] of providers.entries()) {\n const provider = record(item)\n const type = String(provider.type ?? '')\n // Console/API 没有渠道字段,沿用生成应用的 sms Provider 名称识别短信。\n const service = type === 'aliyun-sms' || (['console', 'api'].includes(type) && provider.name === 'sms') ? 'sms' : ['smtp', 'api', 'console'].includes(type) ? 'email' : undefined\n if (service)\n add(service, type, 'reach', ['providers', String(index)], provider, '@h-ai/reach')\n }\n }\n if (deps.has('@h-ai/reach') && !middlewares.some(item => item.configName === 'reach'))\n add('email', 'console', 'reach', ['providers', '0'], { name: 'email', type: 'console' }, '@h-ai/reach')\n const isSvelteKit = graph.build.has('@sveltejs/kit')\n const scan: ScanResult = {\n appDir,\n envDir,\n middlewares,\n haiModules: [...deps].filter(name => name.startsWith('@h-ai/')).sort(),\n appName,\n isSvelteKit,\n adapterInstalled: graph.build.has('@sveltejs/adapter-vercel'),\n nodeAdapterInstalled: graph.build.has('@sveltejs/adapter-node'),\n requiredServices: [...new Set(middlewares.map(item => item.service))],\n serviceBackends: Object.fromEntries(middlewares.map(item => [item.service, item.backend])),\n }\n logger.info('Application scanned', { appName: scan.appName, haiModules: scan.haiModules, requiredServices: scan.requiredServices, serviceBackends: scan.serviceBackends })\n return ok(scan)\n }\n catch {\n // JSON/YAML 异常可能带有凭据行,不把原异常暴露到日志或用户错误。\n return err(HaiDeployError.SCAN_FAILED, deployM('deploy_scanFailed', { params: { error: 'Invalid or ambiguous application/configuration/lockfile; specify the application directory and run pnpm install' } }))\n }\n}\n","/**\n * 生成两个内部部署流程共用的 Compose 容器身份查询函数,不改变容器状态。\n * @returns POSIX Shell 函数 compose_container_ids(runtime, project, service, selector)。\n * @example 模块内部上下文\n * ```ts\n * const lookup = createComposeContainerLookupScript()\n * const apply = [lookup, 'compose_container_ids docker hai-demo-prod db -aq'].join('\\n')\n * // apply 供部署包内部执行,应用调用公开部署 API,不直接执行这段 Shell。\n * void apply\n * ```\n */\nexport function createComposeContainerLookupScript(): string {\n const labelFormat = ['com.docker.compose.project', 'com.docker.compose.service', 'io.podman.compose.project', 'io.podman.compose.service']\n .map(key => `{{index .Config.Labels \\`${key}\\`}}`)\n .join('|')\n return String.raw`compose_container_ids() (\n if [ \"$#\" -ne 4 ]; then printf 'Compose container lookup requires runtime, project, service and selector.\\n' >&2; exit 1; fi\n lookup_runtime=$1\n lookup_project=$2\n lookup_service=$3\n lookup_selector=$4\n case \"$lookup_runtime\" in docker|podman) ;; *) printf 'Invalid Compose lookup runtime.\\n' >&2; exit 1;; esac\n case \"$lookup_project\" in ''|*[!A-Za-z0-9_.-]*) printf 'Invalid Compose project identity.\\n' >&2; exit 1;; esac\n case \"$lookup_service\" in ''|*[!A-Za-z0-9_.-]*) printf 'Invalid Compose service identity.\\n' >&2; exit 1;; esac\n case \"$lookup_selector\" in -q|-aq) ;; *) printf 'Invalid Compose container selector.\\n' >&2; exit 1;; esac\n lookup_ids=''\n for lookup_namespace in com.docker.compose io.podman.compose; do\n lookup_found=$(\"$lookup_runtime\" ps \"$lookup_selector\" --filter \"label=$lookup_namespace.project=$lookup_project\" --filter \"label=$lookup_namespace.service=$lookup_service\") || { printf 'Cannot query Compose containers.\\n' >&2; exit 1; }\n printf '%s\\n' \"$lookup_found\" | LC_ALL=C awk 'NF {if(NF!=1 || $0!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/) exit 1}' || { printf 'Invalid Compose container identifiers.\\n' >&2; exit 1; }\n lookup_ids=$(printf '%s\\n%s\\n' \"$lookup_ids\" \"$lookup_found\" | LC_ALL=C awk 'NF && !seen[$0]++ {print}') || exit 1\n done\n for lookup_id in $lookup_ids; do\n lookup_labels=$(\"$lookup_runtime\" inspect --format '${labelFormat}' \"$lookup_id\") || { printf 'Cannot inspect Compose container labels.\\n' >&2; exit 1; }\n printf '%s\\n' \"$lookup_labels\" | LC_ALL=C awk -F'|' -v project=\"$lookup_project\" -v service=\"$lookup_service\" '\n NR!=1 || NF!=4 {exit 1}\n {\n docker=($1!=\"\" && $1!=\"<no value>\") || ($2!=\"\" && $2!=\"<no value>\")\n podman=($3!=\"\" && $3!=\"<no value>\") || ($4!=\"\" && $4!=\"<no value>\")\n if((!docker && !podman) || (docker && ($1!=project || $2!=service)) || (podman && ($3!=project || $4!=service))) exit 1\n }\n END {if(NR!=1) exit 1}\n ' || { printf 'Container labels do not confirm the requested Compose project and service.\\n' >&2; exit 1; }\n done\n if [ -n \"$lookup_ids\" ]; then printf '%s\\n' \"$lookup_ids\"; fi\n)\n`\n}\n","/** 自建中间件凭据在服务器定稿;打包机仅提供首次部署候选值。 */\nimport { parseEnv } from 'node:util'\nimport { deployM } from '../deploy-i18n.js'\n\nconst groups = [\n { name: 'DB_PASSWORD', keys: ['POSTGRES_PASSWORD', 'MYSQL_PASSWORD', 'MYSQL_ROOT_PASSWORD'], services: ['db', 'vecdb'] },\n { name: 'STORAGE_PASSWORD', keys: ['RUSTFS_SECRET_KEY', 'MINIO_ROOT_PASSWORD'], services: ['storage'] },\n { name: 'LDAP_PASSWORD', keys: ['LDAP_ADMIN_PASSWORD'], services: ['ldap'] },\n]\nconst appPrefixes: Record<string, string> = { db: 'HAI_DB', vecdb: 'HAI_VECDB', storage: 'HAI_STORAGE', ldap: 'HAI_IAM_LDAP' }\n\n/**\n * 按实际 Compose 声明解析命名卷,供凭据与后端身份清单共用。\n * @param projectName - 含环境的部署身份,不含 hai- 前缀。\n * @param mounts - 服务的 Compose volumes 字段。\n * @param declarations - Compose 顶层命名卷声明。\n * @returns 去重后的容器引擎实际卷名;忽略 bind mount。\n * @throws Error - 实际卷名不能安全写入部署清单。\n * @example 模块内部上下文\n * ```ts\n * const volumes = resolveComposeNamedVolumes('shop-prod', ['data:/data'], { data: null })\n * ```\n */\nexport function resolveComposeNamedVolumes(projectName: string, mounts: unknown, declarations: Record<string, unknown> = {}): string[] {\n if (!Array.isArray(mounts))\n return []\n const volumes = new Set<string>()\n for (const mount of mounts) {\n if (typeof mount !== 'string')\n continue\n const source = mount.split(':')[0]!\n if (!Object.hasOwn(declarations, source))\n continue\n const declaration = declarations[source]\n const details = declaration && typeof declaration === 'object' ? declaration : {}\n const volume = 'name' in details && typeof details.name === 'string'\n ? details.name\n : 'external' in details && details.external === true ? source : `hai-${projectName}_${source}`\n if (!/^\\w[\\w.-]*$/.test(volume))\n throw new Error(deployM('deploy_managedSecretsInvalid'))\n volumes.add(volume)\n }\n return [...volumes]\n}\n\n/**\n * 生成候选和卷身份清单;服务器以自己保存的状态覆盖候选,不把本机缓存当作长期凭据。\n * @param projectName - 含环境的部署身份,与 Compose project 参数一致。\n * @param nativeEnvironment - 仅供中间件使用的 dotenv。\n * @param compose - 当前生成的实际服务与命名卷。\n * @param compose.services - 实际启用的 Compose 服务。\n * @param compose.volumes - Compose 命名卷声明。\n * @returns 随不可变部署包传输的私有候选、卷清单和服务器执行脚本。\n * @throws Error - 候选不符合自动生成值格式,或同组凭据互相冲突。\n * @example 模块内部上下文\n * ```ts\n * const assets = createManagedSecretAssets('shop-test', '', { services: {} })\n * const script = assets['resolve-managed-secrets.sh']\n * ```\n */\nexport function createManagedSecretAssets(projectName: string, nativeEnvironment: string, compose: {\n services: Record<string, Record<string, unknown>>\n volumes?: Record<string, unknown>\n}): Record<string, string> {\n const native = parseEnv(nativeEnvironment)\n const candidates: string[] = []\n const bindings = new Set<string>()\n const volumes = new Set<string>()\n for (const group of groups) {\n const values = [...new Set(group.keys.flatMap(key => native[key] === undefined ? [] : [native[key]!]))]\n if (!values.length)\n continue\n if (values.length !== 1 || !/^[\\w-]{32}$/.test(values[0]!))\n throw new Error(deployM('deploy_managedSecretsInvalid'))\n candidates.push(`${group.name}=${values[0]}`)\n for (const key of group.keys.filter(key => native[key] !== undefined))\n bindings.add(`${group.name} ${key} exact`)\n for (const name of group.services) {\n const service = compose.services[name]\n if (!service?.env_file)\n continue\n bindings.add(`${group.name} ${appPrefixes[name]} prefix`)\n for (const volume of resolveComposeNamedVolumes(projectName, service.volumes, compose.volumes))\n volumes.add(`${group.name} ${volume}`)\n }\n }\n return {\n 'managed-project': `hai-${projectName}\\n`,\n 'managed-candidates.env': candidates.length ? `${candidates.join('\\n')}\\n` : '',\n 'managed-bindings': bindings.size ? `${[...bindings].join('\\n')}\\n` : '',\n 'managed-volumes': volumes.size ? `${[...volumes].join('\\n')}\\n` : '',\n 'resolve-managed-secrets.sh': createManagedSecretScript(),\n }\n}\n\n/**\n * 复用现有服务器凭据格式校验,不解码或输出任何凭据值。\n * @returns 定义 valid_values 的纯 Shell 片段,兼容首次候选与受控导入 v2。\n * @example 模块内部上下文\n * ```ts\n * const validation = createManagedSecretValidationScript()\n * const script = [validation, 'valid_values \"$credential_file\"'].join('\\n')\n * // 仅在部署包内校验可信路径,不将凭据内容写入日志或返回给浏览器。\n * void script\n * ```\n */\nexport function createManagedSecretValidationScript(): string {\n return String.raw`valid_values() {\n version=$(awk -F= '$1==\"FORMAT_VERSION\" {print $2}' \"$1\")\n if [ \"$version\" = 2 ]; then\n LC_ALL=C awk -F= '\n NF {\n if(NF!=2 || seen[$1]++) exit 1\n if($1==\"FORMAT_VERSION\") {if($2!=\"2\") exit 1; next}\n if($1==\"PROJECT\") {if($2!~/^[A-Za-z0-9][A-Za-z0-9_.-]*$/) exit 1; project=1; next}\n if($1~/^VOLUME_[0-9]+$/) {if($2!~/^(DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD):[A-Za-z0-9][A-Za-z0-9_.-]*$/) exit 1; next}\n if($1!~/^(DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD)$/ || $2!~/^[0-9a-f]+$/ || length($2)%2 || length($2)>8192) exit 1\n for(i=1;i<=length($2);i+=2) {b=substr($2,i,2); if(b~/^[01]/ || b==\"7f\") exit 1}\n }\n END {if(!project) exit 1}\n ' \"$1\"\n return\n fi\n LC_ALL=C awk -F= '\n NF {if(NF!=2 || $1!~/^(DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD)$/ || $2!~/^[A-Za-z0-9_-]+$/ || length($2)!=32 || seen[$1]++) exit 1}\n ' \"$1\"\n}\n`\n}\n\n/** 由 apply.sh 持有项目部署锁时调用,不输出密码值。 */\nfunction createManagedSecretScript(): string {\n return String.raw`#!/bin/sh\n# 由 apply.sh 在项目部署锁内调用;长期凭据只保存在服务器,不依赖打包机。\nset -eu\numask 077\nroot=$1\nrelease=$2\nruntime=$3\nstate=\"$root/managed-secrets.env\"\ncandidate_file=\"$release/managed-candidates.env\"\ntest -s \"$candidate_file\" || exit 0\nfail() { printf '%s\\n' \"$*\" >&2; exit 1; }\n@@MANAGED_VALUES_VALIDATOR@@\nvalue_of() { awk -F= -v key=\"$2\" '$1==key {print $2}' \"$1\"; }\ntest ! -L \"$state\" || fail \"Invalid managed middleware credential state: $state\"\nvalid_values \"$candidate_file\" || fail 'Invalid managed middleware credential candidates; rebuild the deployment bundle.'\nnext=\"$release/managed-secrets.next\"\nif [ -f \"$state\" ]; then\n test -s \"$state\" && valid_values \"$state\" || fail \"Invalid managed middleware credential state: $state. Restore its protected backup.\"\n cp \"$state\" \"$next\"\nelse\n : > \"$next\"\nfi\nformat=$(value_of \"$next\" FORMAT_VERSION)\nif [ \"$format\" = 2 ]; then\n test \"$(value_of \"$next\" PROJECT)\" = \"$(cat \"$release/managed-project\")\" || fail 'Managed middleware credential project mismatch.'\n known=$(\"$runtime\" volume ls -q) || fail 'Cannot check persistent volumes; managed middleware credentials were not changed.'\n while IFS=' ' read -r volume_group volume; do\n test -n \"$volume\" || continue\n binding=\"$volume_group:$volume\"\n if ! awk -F= -v binding=\"$binding\" '$1~/^VOLUME_[0-9]+$/ && $2==binding {found=1} END {exit !found}' \"$next\"; then\n if printf '%s\\n' \"$known\" | grep -Fxq \"$volume\"; then\n fail 'Existing persistent volume is not bound to the imported credential state. Import its verified identity first.'\n fi\n index=$(awk -F= '$1~/^VOLUME_[0-9]+$/ {n=substr($1,8)+0; if(n>max)max=n} END {print max+1}' \"$next\")\n printf 'VOLUME_%s=%s\\n' \"$index\" \"$binding\" >> \"$next\"\n fi\n done < \"$release/managed-volumes\"\nfi\nvolumes_checked=false\nknown_volumes=''\nwhile IFS='=' read -r name candidate; do\n test -n \"$name\" || continue\n value=$(value_of \"$next\" \"$name\")\n if [ -z \"$value\" ]; then\n if [ \"$volumes_checked\" = false ]; then\n known_volumes=$(\"$runtime\" volume ls -q) || fail 'Cannot check persistent volumes; managed middleware credentials were not changed.'\n volumes_checked=true\n fi\n while IFS=' ' read -r volume_group volume; do\n test \"$volume_group\" = \"$name\" || continue\n if printf '%s\\n' \"$known_volumes\" | grep -Fxq \"$volume\"; then\n fail \"Missing $name in $state for existing persistent volume $volume. Restore the server credential state before retrying.\"\n fi\n done < \"$release/managed-volumes\"\n value=$candidate\n if [ \"$format\" = 2 ]; then value=$(printf '%s' \"$candidate\" | od -An -tx1 | tr -d ' \\n'); fi\n printf '%s=%s\\n' \"$name\" \"$value\" >> \"$next\"\n fi\ndone < \"$candidate_file\"\nwhile IFS='=' read -r name candidate; do\n test -n \"$name\" || continue\n value=$(value_of \"$next\" \"$name\")\n for file in .env.runtime middleware.env middleware-runtime.env; do\n HAI_DEPLOY_SECRET_CANDIDATE=\"$candidate\" HAI_DEPLOY_SECRET_VALUE=\"$value\" LC_ALL=C awk -v group=\"$name\" -v format=\"$format\" '\n FILENAME==ARGV[1] {if($1==group) {keys[$2]=$3}; next}\n function replace_literal(line, needle, value, result, at) {\n result=\"\"\n while((at=index(line,needle))>0) {result=result substr(line,1,at-1) value; line=substr(line,at+length(needle))}\n return result line\n }\n function decode_hex(hex, result, i, high, low) {\n for(i=1;i<=length(hex);i+=2) {high=index(\"0123456789abcdef\",substr(hex,i,1))-1; low=index(\"0123456789abcdef\",substr(hex,i+1,1))-1; result=result sprintf(\"%c\",high*16+low)}\n return result\n }\n function json_escape(value, apostrophe, result, i, ch) {\n for(i=1;i<=length(value);i++) {\n ch=substr(value,i,1)\n if(ch==\"\\\\\") result=result \"\\\\\\\\\"\n else if(ch==\"\\\"\") result=result \"\\\\\\\"\"\n else if(ch==sprintf(\"%c\",39) && apostrophe) result=result \"\\\\u0027\"\n else result=result ch\n }\n return result\n }\n function uri_escape(value, result, i, ch, j, ordinal) {\n for(i=1;i<=length(value);i++) {\n ch=substr(value,i,1)\n if(ch~/[A-Za-z0-9_.~-]/) result=result ch\n else {ordinal=0; for(j=1;j<=255;j++) if(sprintf(\"%c\",j)==ch) {ordinal=j; break}; result=result sprintf(\"%%%02X\",ordinal)}\n }\n return result\n }\n {\n equal=index($0,\"=\"); key=substr($0,1,equal-1); scoped=0\n for(prefix in keys) if(key==prefix || (keys[prefix]==\"prefix\" && index(key,prefix \"_\")==1)) scoped=1\n if(scoped && format==2 && index($0,ENVIRON[\"HAI_DEPLOY_SECRET_CANDIDATE\"])>0) {\n candidate=ENVIRON[\"HAI_DEPLOY_SECRET_CANDIDATE\"]; value=decode_hex(ENVIRON[\"HAI_DEPLOY_SECRET_VALUE\"])\n literal=substr($0,equal+1); quote=sprintf(\"%c\",39)\n json=substr(literal,1,1)==quote && (substr(literal,2,1)==\"{\" || substr(literal,2,1)==\"[\")\n if(json) literal=substr(literal,2,length(literal)-2)\n literal=replace_literal(literal,\":\" candidate \"@\",\":\" uri_escape(value) \"@\")\n if(json) {literal=replace_literal(literal,candidate,json_escape(value,1)); print key \"=\" quote literal quote}\n else {\n if(substr(literal,1,1)==quote || substr(literal,1,1)==\"\\\"\") literal=substr(literal,2,length(literal)-2)\n literal=replace_literal(literal,candidate,value)\n literal=json_escape(literal,0); literal=replace_literal(literal,\"$\",\"$$\")\n print key \"=\\\"\" literal \"\\\"\"\n }\n }\n else if(scoped) print replace_literal($0,ENVIRON[\"HAI_DEPLOY_SECRET_CANDIDATE\"],ENVIRON[\"HAI_DEPLOY_SECRET_VALUE\"])\n else print\n }\n ' \"$release/managed-bindings\" \"$release/$file\" > \"$release/$file.next\"\n mv \"$release/$file.next\" \"$release/$file\"\n done\ndone < \"$candidate_file\"\nchmod 600 \"$next\"\nmv \"$next\" \"$state\"\nprintf '[INFO] Managed middleware credential source: %s (server state; values hidden).\\n' \"$state\"\n`.replace('@@MANAGED_VALUES_VALIDATOR@@', createManagedSecretValidationScript())\n}\n","/** 命名卷的后端身份独立于 current 拓扑保存,禁止把旧数据目录交给不兼容引擎。 */\nimport { deployM } from '../deploy-i18n.js'\nimport { createComposeContainerLookupScript } from './deploy-compose-identity.js'\nimport { createManagedSecretValidationScript, resolveComposeNamedVolumes } from './deploy-managed-secrets.js'\n\nconst backendFamilies: Record<string, readonly string[]> = {\n db: ['postgresql', 'mysql'],\n storage: ['rustfs', 'minio'],\n vecdb: ['qdrant', 'pgvector', 'chroma'],\n}\n\n/**\n * 为不可变部署包生成实际卷绑定和服务器校验脚本,仅供模块内部打包流程调用。\n * @param projectName - 已归一化、含环境的部署身份。\n * @param compose - 当前实际 Compose 服务与命名卷声明。\n * @param compose.services - 实际服务定义。\n * @param compose.volumes - 命名卷定义。\n * @param selected - 本包更新的服务;未选服务由成功基线补齐。\n * @returns 三列 state-backends 与固定本地引擎的身份校验脚本。\n * @throws Error - 有状态服务的引擎或实际卷绑定不符合生成契约。\n * @example 模块内部上下文\n * ```ts\n * const assets = createBackendStateAssets('shop-prod', { services: { db: { image: 'postgres:16', volumes: ['data:/data'] } }, volumes: { data: null } }, ['db'])\n * ```\n */\nexport function createBackendStateAssets(projectName: string, compose: {\n services: Record<string, Record<string, unknown>>\n volumes?: Record<string, unknown>\n}, selected: readonly string[]): Record<string, string> {\n if (!/^[\\w.-]+$/.test(projectName))\n throw new Error(deployM('deploy_artifactInvalid'))\n const tuples: string[] = []\n const volumes = new Set<string>()\n for (const serviceName of selected) {\n const families = backendFamilies[serviceName]\n if (!families)\n continue\n const service = compose.services[serviceName]\n const image = service?.image\n if (typeof image !== 'string')\n throw new Error(deployM('deploy_artifactInvalid'))\n const imageFamily = image.slice(image.lastIndexOf('/') + 1).split(':')[0]!\n const family = imageFamily === 'postgres' ? 'postgresql' : imageFamily\n const namedVolumes = resolveComposeNamedVolumes(projectName, service.volumes, compose.volumes)\n if (!families.includes(family) || namedVolumes.length !== 1 || volumes.has(namedVolumes[0]!))\n throw new Error(deployM('deploy_artifactInvalid'))\n const volume = namedVolumes[0]!\n volumes.add(volume)\n tuples.push(`${serviceName} ${family} ${volume}`)\n }\n return {\n 'state-backends': tuples.length ? `${tuples.join('\\n')}\\n` : '',\n 'resolve-backend-state.sh': createBackendStateScript()\n .replace('@@PROJECT@@', projectName)\n .replace('@@MANAGED_VALUES_VALIDATOR@@', createManagedSecretValidationScript())\n .replace('@@COMPOSE_CONTAINER_LOOKUP@@', createComposeContainerLookupScript()),\n }\n}\n\n/** 只在 apply.sh 持有项目部署锁时执行,不执行配置文件中的代码,不输出凭据。 */\nfunction createBackendStateScript(): string {\n return String.raw`#!/bin/sh\nset -eu\numask 077\nfail() { printf '%s\\n' \"$*\" >&2; exit 1; }\ntest \"$#\" -eq 5 || fail 'Backend state requires root, release, runtime, previous ID and mode.'\nroot=$1\nrelease=$2\nruntime=$3\nprevious=$4\nmode=$5\nproject='hai-@@PROJECT@@'\nstate=\"$root/persistent-backends\"\nsnapshot=\"$release/previous-state-backends\"\ncase \"$mode\" in check|commit|recover) ;; *) fail 'Invalid backend state mode.';; esac\ncase \"$runtime\" in docker|podman) ;; *) fail 'Backend state requires a resolved container runtime.';; esac\ncase \"$previous\" in .|..|*[!A-Za-z0-9_.-]*) fail 'Invalid previous deployment identity.';; esac\ntest -d \"$root\" && test ! -L \"$root\" && test -d \"$release\" && test ! -L \"$release\" || fail 'Invalid backend state directory.'\nregular() { test -f \"$1\" && test ! -L \"$1\" || fail \"Backend state must be a regular file: $1\"; }\nabsent_or_regular() { if [ -e \"$1\" ] || [ -L \"$1\" ]; then regular \"$1\"; fi; }\nvalid_tuples() {\n LC_ALL=C awk -v legacy=\"$2\" '\n NF {\n if((NF!=3 && !(legacy==1 && NF==2)) || roles[$1]++) exit 1\n if(!(($1==\"db\" && $2~/^(postgresql|mysql)$/) || ($1==\"storage\" && $2~/^(rustfs|minio)$/) || ($1==\"vecdb\" && $2~/^(qdrant|pgvector|chroma)$/))) exit 1\n if(NF==3 && ($3!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ || volumes[$3]++)) exit 1\n }\n ' \"$1\"\n}\nvalid_state() {\n LC_ALL=C awk -v snapshot=\"$2\" '\n NR==1 {if($0!=\"FORMAT_VERSION 1\") exit 1; next}\n NR==2 {if(NF!=2 || $1!=\"RUNTIME\" || $2!~/^(docker|podman)$/) exit 1; next}\n NR==3 {if(NF!=2 || $1!=\"UID\" || $2!~/^[0-9]+$/) exit 1; next}\n NR==4 {if(NF!=2 || $1!=\"IDENTITY\" || $2!~/^[0-9a-f]+$/ || length($2)!=64) exit 1; next}\n NR==5 {if(NF!=2 || $1!=\"PROJECT\" || $2!~/^hai-[A-Za-z0-9_.-]+$/) exit 1; next}\n NR==6 && snapshot==1 {if(NF!=2 || $1!=\"PREVIOUS\" || $2!~/^[A-Za-z0-9_.-]+$/) exit 1; next}\n {\n if(NF!=3 || volumes[$3]++ || (snapshot==1 && roles[$1]++)) exit 1\n if(!(($1==\"db\" && $2~/^(postgresql|mysql)$/) || ($1==\"storage\" && $2~/^(rustfs|minio)$/) || ($1==\"vecdb\" && $2~/^(qdrant|pgvector|chroma)$/))) exit 1\n if($3!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/) exit 1\n }\n END {if(NR<5+snapshot) exit 1}\n ' \"$1\"\n}\n# 本机制只支持固定用户的本地默认引擎。连接名称或路径不证明数据格式,更换存储需独立迁移。\nenv | LC_ALL=C awk -F= '$1~/^(DOCKER_HOST|DOCKER_CONTEXT|CONTAINER_HOST|CONTAINER_CONNECTION|CONTAINERS_STORAGE_CONF|CONTAINERS_CONF|STORAGE_DRIVER|STORAGE_OPTS)$/ && length(substr($0,index($0,\"=\")+1)) {exit 1}' || fail 'Remote or overridden container storage is unsupported for persistent backend state. Use a fixed local default engine.'\nowner=$(id -u) || fail 'Cannot identify the deployment user.'\ncase \"$owner\" in ''|*[!0-9]*) fail 'Invalid deployment user identity.';; esac\nif [ \"$runtime\" = docker ]; then\n context=$(docker context show) || fail 'Cannot check the Docker context.'\n test \"$context\" = default || fail 'Persistent backend state requires the default local Docker context.'\n engine=$(docker info --format '{{.ID}}|{{.DockerRootDir}}|{{.Driver}}') || fail 'Cannot identify the local Docker daemon.'\nelse\n remote=$(podman info --format '{{.Host.ServiceIsRemote}}') || fail 'Cannot check whether Podman is local.'\n test \"$remote\" = false || fail 'Persistent backend state requires local Podman; remote connections are unsupported.'\n engine=$(podman info --format '{{.Host.Hostname}}|{{.Store.GraphRoot}}|{{.Store.GraphDriverName}}') || fail 'Cannot identify the local Podman store.'\nfi\nprintf '%s\\n' \"$engine\" | LC_ALL=C awk -F'|' 'NR!=1 || NF!=3 || $1==\"\" || $1==\"<no value>\" || $2!~/^\\// || $3==\"\" || $3==\"<no value>\" {exit 1}' || fail 'Incomplete container store identity; no services were started.'\nidentity=$(printf '%s\\n%s\\n%s\\n' \"$runtime\" \"$owner\" \"$engine\" | sha256sum | awk '{print $1}')\nprintf '%s\\n' \"$identity\" | LC_ALL=C awk 'NR!=1 || $0!~/^[0-9a-f]+$/ || length($0)!=64 {exit 1}' || fail 'Cannot calculate the container store identity.'\nheader=$(printf 'FORMAT_VERSION 1\\nRUNTIME %s\\nUID %s\\nIDENTITY %s\\nPROJECT %s' \"$runtime\" \"$owner\" \"$identity\" \"$project\")\nsame_identity() {\n test \"$(sed -n '1,5p' \"$1\")\" = \"$header\" || fail 'Deployment project, container runtime, user or daemon/store identity changed. Use a separate deployment identity and migrate or restore data explicitly.'\n}\nabsent_or_regular \"$state\"\nledger=''\nif [ -f \"$state\" ]; then\n valid_state \"$state\" 0 || fail 'Invalid persistent backend ledger. Restore its protected backup.'\n same_identity \"$state\"\n ledger=$(sed -n '6,$p' \"$state\")\nfi\nknown=$(\"$runtime\" volume ls -q) || fail 'Cannot list persistent volumes; no backend state was changed.'\nprintf '%s\\n' \"$known\" | LC_ALL=C awk 'NF {if(NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ || seen[$1]++) exit 1}' || fail 'Invalid persistent volume listing.'\nexists_volume() { printf '%s\\n' \"$known\" | grep -Fxq \"$1\"; }\nledger_tuple() { printf '%s\\n' \"$ledger\" | awk -v volume=\"$1\" '$3==volume {print}'; }\n@@MANAGED_VALUES_VALIDATOR@@\n@@COMPOSE_CONTAINER_LOOKUP@@\n# 仅供旧状态补证:卷挂载和镜像均取自同项目、同角色的唯一实际容器。\ncontainer_binding() {\n binding_service=$1\n binding_family=$2\n binding_expected=$3\n binding_running=$4\n binding_flags=-aq\n if [ \"$binding_running\" = true ]; then binding_flags=-q; fi\n binding_containers=$(compose_container_ids \"$runtime\" \"$project\" \"$binding_service\" \"$binding_flags\") || fail 'Cannot inspect successful deployment containers.'\n printf '%s\\n' \"$binding_containers\" | LC_ALL=C awk 'NR!=1 || NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ {exit 1} END {if(NR!=1) exit 1}' || fail \"Cannot prove the previous volume binding for $binding_service. Restore verified backend state.\"\n if [ \"$binding_running\" = true ]; then\n binding_status=$(\"$runtime\" inspect --format '{{.State.Running}}' \"$binding_containers\") || fail 'Cannot verify the imported service is running.'\n test \"$binding_status\" = true || fail \"Imported backend requires its verified original container to be running: $binding_service.\"\n fi\n binding_mounted=$(\"$runtime\" inspect --format '{{range .Mounts}}{{if eq .Type \"volume\"}}{{println .Name}}{{end}}{{end}}' \"$binding_containers\") || fail 'Cannot inspect previous named volume mounts.'\n printf '%s\\n' \"$binding_mounted\" | LC_ALL=C awk 'NR!=1 || NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ {exit 1} END {if(NR!=1) exit 1}' || fail \"Ambiguous previous volume binding for $binding_service.\"\n binding_image=$(\"$runtime\" inspect --format '{{.Config.Image}}' \"$binding_containers\") || fail 'Cannot identify the previous container image.'\n binding_actual_family=$(printf '%s\\n' \"$binding_image\" | LC_ALL=C awk 'NR!=1 || NF!=1 {exit 1} {image=$0; sub(/^.*\\//,\"\",image); sub(/[:@].*$/,\"\",image); if(image==\"postgres\") image=\"postgresql\"; print image}') || fail 'Invalid previous container image identity.'\n test \"$binding_actual_family\" = \"$binding_family\" || fail \"Actual previous container image does not confirm its backend family: $binding_service.\"\n if [ -n \"$binding_expected\" ] && [ \"$binding_expected\" != \"$binding_mounted\" ]; then fail \"Actual previous volume differs from its backend manifest: $binding_service.\"; fi\n printf '%s\\n' \"$binding_mounted\"\n}\nconfirmed_import() {\n import_service=$1\n import_family=$2\n import_volume=$3\n import_state=\"$root/managed-secrets.env\"\n test -f \"$import_state\" && test ! -L \"$import_state\" || return 1\n valid_values \"$import_state\" || return 1\n test \"$(awk -F= '$1==\"FORMAT_VERSION\" {print $2}' \"$import_state\")\" = 2 || return 1\n test \"$(awk -F= '$1==\"PROJECT\" {print $2}' \"$import_state\")\" = \"$project\" || return 1\n case \"$import_service\" in db|vecdb) import_group=DB_PASSWORD;; storage) import_group=STORAGE_PASSWORD;; *) return 1;; esac\n awk -F= -v group=\"$import_group\" -v binding=\"$import_group:$import_volume\" '$1==group && $2!=\"\" {credential=1} $1~/^VOLUME_[0-9]+$/ && $2==binding {volume=1} END {exit !(credential && volume)}' \"$import_state\" || return 1\n # 密码不证明目录格式;受控导入还须与唯一运行原容器的实际卷及镜像家族共同吻合。\n import_actual=$(container_binding \"$import_service\" \"$import_family\" \"$import_volume\" true) || return 1\n test \"$import_actual\" = \"$import_volume\"\n}\nsnapshot_previous=$previous\nif [ -z \"$snapshot_previous\" ]; then snapshot_previous=-; fi\nif [ \"$mode\" = recover ]; then\n regular \"$snapshot\"\n valid_state \"$snapshot\" 1 || fail 'Invalid previous backend snapshot; automatic recovery is refused.'\n same_identity \"$snapshot\"\n test \"$(sed -n '6p' \"$snapshot\")\" = \"PREVIOUS $snapshot_previous\" || fail 'Previous backend snapshot does not match the recovery release.'\n while IFS=' ' read -r recover_service recover_family recover_volume; do\n test -n \"$recover_service\" || continue\n exists_volume \"$recover_volume\" || fail \"Previous persistent volume is missing: $recover_volume. Restore its backup before recovery.\"\n test \"$(ledger_tuple \"$recover_volume\")\" = \"$recover_service $recover_family $recover_volume\" || fail \"Previous persistent backend identity is unconfirmed: $recover_service. Automatic recovery is refused.\"\n done <<RECOVERY_TUPLES\n$(sed -n '7,$p' \"$snapshot\")\nRECOVERY_TUPLES\n exit 0\nfi\nregular \"$release/state-backends\"\nvalid_tuples \"$release/state-backends\" 0 || fail 'Invalid backend manifest; rebuild the deployment bundle.'\nactive=''\nif [ -n \"$previous\" ]; then\n baseline=\"$root/releases/$previous\"\n test -d \"$root/releases\" && test ! -L \"$root/releases\" && test -d \"$baseline\" && test ! -L \"$baseline\" || fail 'Invalid successful deployment directory.'\n regular \"$baseline/services\"\n regular \"$baseline/compose-files\"\n LC_ALL=C awk 'NF {if(NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ || seen[$1]++) exit 1}' \"$baseline/services\" || fail 'Invalid successful deployment services.'\n for active_service in db storage vecdb; do\n if ! grep -Fxq \"$active_service\" \"$baseline/services\"; then continue; fi\n active_family=''\n active_volume=''\n while IFS= read -r compose_file; do\n compose_directory=$(dirname -- \"$compose_file\")\n compose_id=$(basename -- \"$compose_directory\")\n case \"$compose_id\" in ''|.|..|*[!A-Za-z0-9_.-]*) fail 'Invalid successful Compose identity.';; esac\n test \"$compose_directory\" = \"$root/releases/$compose_id\" && test ! -L \"$compose_directory\" || fail 'Successful Compose file escapes the deployment directory.'\n regular \"$compose_file\"\n previous_manifest=\"$compose_directory/state-backends\"\n absent_or_regular \"$previous_manifest\"\n if [ -f \"$previous_manifest\" ]; then\n valid_tuples \"$previous_manifest\" 1 || fail 'Invalid successful backend manifest.'\n recorded=$(awk -v service=\"$active_service\" '$1==service {print}' \"$previous_manifest\")\n if [ -n \"$recorded\" ]; then\n active_family=$(printf '%s\\n' \"$recorded\" | awk '{print $2}')\n active_volume=$(printf '%s\\n' \"$recorded\" | awk '{print $3}')\n fi\n fi\n done < \"$baseline/compose-files\"\n if [ -z \"$active_family\" ]; then\n # 兼容旧包只读取已知字段,不 source dotenv;凭据本身不是后端身份的证据。\n case \"$active_service\" in\n db|vecdb)\n regular \"$baseline/middleware.env\"\n state_key=HAI_DB\n if [ \"$active_service\" = vecdb ]; then state_key=HAI_VECDB; fi\n active_family=$(awk -F= -v key=\"$state_key\" '$1==key {if($0~/\"type\"[[:space:]]*:[[:space:]]*\"postgresql\"/) print \"postgresql\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"mysql\"/) print \"mysql\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"qdrant\"/) print \"qdrant\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"pgvector\"/) print \"pgvector\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"chroma\"/) print \"chroma\"}' \"$baseline/middleware.env\")\n ;;\n storage)\n regular \"$baseline/middleware-runtime.env\"\n active_family=$(awk -F= '$1==\"RUSTFS_SECRET_KEY\" {print \"rustfs\"} $1==\"MINIO_ROOT_PASSWORD\" {print \"minio\"}' \"$baseline/middleware-runtime.env\")\n ;;\n esac\n fi\n # 旧两列清单或丢失账本只能以当前真实容器的命名卷挂载补证,不猜默认卷名。\n if [ -z \"$active_volume\" ] || [ -z \"$(ledger_tuple \"$active_volume\")\" ]; then\n active_volume=$(container_binding \"$active_service\" \"$active_family\" \"$active_volume\" false) || fail \"Cannot confirm the active persistent backend: $active_service.\"\n fi\n printf '%s %s %s\\n' \"$active_service\" \"$active_family\" \"$active_volume\" | LC_ALL=C awk 'NF!=3 || !(($1==\"db\" && $2~/^(postgresql|mysql)$/) || ($1==\"storage\" && $2~/^(rustfs|minio)$/) || ($1==\"vecdb\" && $2~/^(qdrant|pgvector|chroma)$/)) {exit 1}' || fail \"Unknown previous backend for $active_service; explicit migration is required.\"\n exists_volume \"$active_volume\" || fail \"Active persistent volume is missing: $active_volume. Restore its backup instead of creating an empty replacement.\"\n confirmed=$(ledger_tuple \"$active_volume\")\n test -z \"$confirmed\" || test \"$confirmed\" = \"$active_service $active_family $active_volume\" || fail \"Active persistent backend conflicts with the protected ledger: $active_service.\"\n active=$(printf '%s\\n%s %s %s\\n' \"$active\" \"$active_service\" \"$active_family\" \"$active_volume\" | sed '/^$/d')\n done\nfi\n# 各个旧 Compose 片段不能把同一实际卷重复绑定给不同有状态角色。\nprintf '%s\\n' \"$active\" | valid_tuples /dev/stdin 0 || fail 'Conflicting successful persistent volume bindings.'\n# 合并时只替换同一卷的无数据预认领,不能按本次拓扑裁剪历史绑定。\nmerged=$ledger\nmerge_tuple() {\n merged=$(printf '%s\\n' \"$merged\" | awk -v volume=\"$3\" 'NF && $3!=volume {print}')\n merged=$(printf '%s\\n%s %s %s\\n' \"$merged\" \"$1\" \"$2\" \"$3\" | sed '/^$/d')\n}\nwhile IFS=' ' read -r active_service active_family active_volume; do\n test -n \"$active_service\" || continue\n merge_tuple \"$active_service\" \"$active_family\" \"$active_volume\"\ndone <<ACTIVE_TUPLES\n$active\nACTIVE_TUPLES\nwhile IFS=' ' read -r candidate_service candidate_family candidate_volume; do\n test -n \"$candidate_service\" || continue\n prior_active=$(printf '%s\\n' \"$active\" | awk -v service=\"$candidate_service\" '$1==service {print}')\n tuple=\"$candidate_service $candidate_family $candidate_volume\"\n test -z \"$prior_active\" || test \"$prior_active\" = \"$tuple\" || fail \"Persistent backend $candidate_service changed or its active volume binding changed. Use a separate deployment identity and migrate or restore data explicitly.\"\n if exists_volume \"$candidate_volume\"; then\n confirmed=$(ledger_tuple \"$candidate_volume\")\n if [ -z \"$confirmed\" ]; then confirmed=$(printf '%s\\n' \"$active\" | awk -v volume=\"$candidate_volume\" '$3==volume {print}'); fi\n if [ -z \"$confirmed\" ] && confirmed_import \"$candidate_service\" \"$candidate_family\" \"$candidate_volume\"; then confirmed=$tuple; fi\n test \"$confirmed\" = \"$tuple\" || fail \"Existing persistent volume has an unknown or incompatible backend: $candidate_service. Restore verified backend state; in-place reuse is refused.\"\n else\n users=$(\"$runtime\" ps -aq --filter \"volume=$candidate_volume\") || fail 'Cannot check persistent volume users.'\n test -z \"$users\" || fail \"A container still references missing persistent volume $candidate_volume. Restore or migrate explicitly.\"\n fi\n merge_tuple \"$candidate_service\" \"$candidate_family\" \"$candidate_volume\"\ndone < \"$release/state-backends\"\nabsent_or_regular \"$snapshot\"\nif [ -e \"$snapshot.next\" ] || [ -L \"$snapshot.next\" ] || [ -e \"$state.next\" ] || [ -L \"$state.next\" ]; then fail 'Backend state staging file already exists; inspect the interrupted deployment before retrying.'; fi\nif [ \"$mode\" = check ]; then exit 0; fi\nsnapshot_content=$(printf '%s\\nPREVIOUS %s\\n' \"$header\" \"$snapshot_previous\"; if [ -n \"$active\" ]; then printf '%s\\n' \"$active\"; fi)\nstate_content=$(printf '%s\\n' \"$header\"; if [ -n \"$merged\" ]; then printf '%s\\n' \"$merged\"; fi)\n# 独占创建同目录临时文件;只有完整快照与账本均落盘后,主流程才可启动或恢复服务。\n(set -C; printf '%s\\n' \"$snapshot_content\" > \"$snapshot.next\") || fail 'Cannot stage the previous backend snapshot.'\nchmod 600 \"$snapshot.next\"\nmv -f -- \"$snapshot.next\" \"$snapshot\"\n(set -C; printf '%s\\n' \"$state_content\" > \"$state.next\") || fail 'Cannot stage the persistent backend ledger.'\nchmod 600 \"$state.next\"\nmv -f -- \"$state.next\" \"$state\"\n`\n}\n","/** Windows Job Object 桥接:静态代码内嵌在包中,参数只通过私有环境入口传递。 */\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\n\n// Native 结构与语义按 Windows SDK;创建时挂起,分配成功后才恢复,避免子进程逃离 Job。\n// https://learn.microsoft.com/windows/win32/procthread/job-objects\nconst nativeJob = String.raw`\nusing System;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\n\npublic static class HaiCommandJob {\n [StructLayout(LayoutKind.Sequential)] struct BasicLimits {\n public long ProcessTime, JobTime;\n public uint Flags;\n public UIntPtr MinimumWorkingSet, MaximumWorkingSet;\n public uint ActiveProcessLimit;\n public UIntPtr Affinity;\n public uint PriorityClass, SchedulingClass;\n }\n [StructLayout(LayoutKind.Sequential)] struct IoCounters {\n public ulong ReadOperations, WriteOperations, OtherOperations, ReadBytes, WriteBytes, OtherBytes;\n }\n [StructLayout(LayoutKind.Sequential)] struct ExtendedLimits {\n public BasicLimits Basic;\n public IoCounters Io;\n public UIntPtr ProcessMemory, JobMemory, PeakProcessMemory, PeakJobMemory;\n }\n [StructLayout(LayoutKind.Sequential)] struct Accounting {\n public long UserTime, KernelTime, PeriodUserTime, PeriodKernelTime;\n public uint Faults, Total, Active, Terminated;\n }\n [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct Startup {\n public uint Size;\n public string Reserved, Desktop, Title;\n public uint X, Y, Width, Height, XChars, YChars, Fill, Flags;\n public ushort Show, ReservedSize;\n public IntPtr ReservedData, Input, Output, Error;\n }\n [StructLayout(LayoutKind.Sequential)] struct ProcessInfo {\n public IntPtr Process, Thread;\n public uint ProcessId, ThreadId;\n }\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr CreateJobObject(IntPtr attributes, string name);\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr OpenJobObject(uint access, bool inherit, string name);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool SetInformationJobObject(IntPtr job, int kind, ref ExtendedLimits information, uint size);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool QueryInformationJobObject(IntPtr job, int kind, out Accounting information, uint size, IntPtr length);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool CreateProcess(string application, StringBuilder command, IntPtr processAttributes, IntPtr threadAttributes, bool inherit, uint flags, IntPtr environment, string directory, ref Startup startup, out ProcessInfo information);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern uint ResumeThread(IntPtr thread);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool TerminateProcess(IntPtr process, uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool TerminateJobObject(IntPtr job, uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool GetExitCodeProcess(IntPtr process, out uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool CloseHandle(IntPtr handle);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern IntPtr GetStdHandle(int kind);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool SetHandleInformation(IntPtr handle, uint mask, uint flags);\n\n static void Check(bool success) { if (!success) throw new Win32Exception(Marshal.GetLastWin32Error()); }\n static uint Active(IntPtr job) {\n Accounting information;\n Check(QueryInformationJobObject(job, 1, out information, (uint)Marshal.SizeOf(typeof(Accounting)), IntPtr.Zero));\n return information.Active;\n }\n // Windows argv 编码:引号前与结尾的反斜杠加倍,其余字符原样传递,不经过命令 shell。\n static string Quote(string value) {\n StringBuilder result = new StringBuilder(\"\\\"\");\n int slashes = 0;\n foreach (char current in value) {\n if (current == '\\\\') { slashes++; continue; }\n if (current == '\"') result.Append('\\\\', slashes * 2 + 1);\n else result.Append('\\\\', slashes);\n result.Append(current);\n slashes = 0;\n }\n result.Append('\\\\', slashes * 2).Append('\"');\n return result.ToString();\n }\n public static int Run(string name, string command, string[] arguments) {\n IntPtr job = CreateJobObject(IntPtr.Zero, name);\n if (job == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());\n ProcessInfo process = new ProcessInfo();\n bool assigned = false;\n try {\n ExtendedLimits limits = new ExtendedLimits();\n limits.Basic.Flags = 0x2000; // JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;不允许 breakaway。\n Check(SetInformationJobObject(job, 9, ref limits, (uint)Marshal.SizeOf(typeof(ExtendedLimits))));\n StringBuilder line = new StringBuilder(Quote(command));\n foreach (string argument in arguments) line.Append(' ').Append(Quote(argument));\n Startup startup = new Startup();\n startup.Size = (uint)Marshal.SizeOf(typeof(Startup));\n startup.Flags = 0x100;\n startup.Input = GetStdHandle(-10); startup.Output = GetStdHandle(-11); startup.Error = GetStdHandle(-12);\n Check(SetHandleInformation(startup.Input, 1, 1));\n Check(SetHandleInformation(startup.Output, 1, 1));\n Check(SetHandleInformation(startup.Error, 1, 1));\n Check(CreateProcess(null, line, IntPtr.Zero, IntPtr.Zero, true, 0x08000004, IntPtr.Zero, null, ref startup, out process));\n Check(AssignProcessToJobObject(job, process.Process));\n assigned = true;\n if (ResumeThread(process.Thread) == 0xFFFFFFFF) throw new Win32Exception(Marshal.GetLastWin32Error());\n if (WaitForSingleObject(process.Process, 0xFFFFFFFF) != 0) throw new Win32Exception(Marshal.GetLastWin32Error());\n uint code;\n Check(GetExitCodeProcess(process.Process, out code));\n while (Active(job) != 0) Thread.Sleep(20);\n return unchecked((int)code);\n }\n finally {\n if (process.Process != IntPtr.Zero) {\n // 分配失败时进程仍挂起,直接终止,不允许裸进程恢复;Job 在其他异常时同样清空。\n if (!assigned) TerminateProcess(process.Process, 125);\n else TerminateJobObject(job, 125);\n WaitForSingleObject(process.Process, 5000);\n }\n if (process.Thread != IntPtr.Zero) CloseHandle(process.Thread);\n if (process.Process != IntPtr.Zero) CloseHandle(process.Process);\n CloseHandle(job);\n }\n }\n public static bool Empty(string name) {\n IntPtr job = OpenJobObject(4, false, name); // JOB_OBJECT_QUERY\n if (job == IntPtr.Zero) {\n if (Marshal.GetLastWin32Error() == 2) return true;\n throw new Win32Exception(Marshal.GetLastWin32Error());\n }\n try { return Active(job) == 0; }\n finally { CloseHandle(job); }\n }\n}\n`\n\n/** 生成隐藏 PowerShell 的静态脚本;执行策略不影响内联命令,不加载用户 profile。 */\nfunction powershell(script: string): string[] {\n return ['-NoLogo', '-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(script, 'utf16le').toString('base64')]\n}\n\n/**\n * 创建命令 Job;参数不插入代码,启动失败直接拒绝,不能降级为无 Job 的裸进程。\n * 只生成 Job helper 的参数和私有环境载荷;调用者必须按约定启动 helper,不能直接恢复裸子进程。\n * @param command - 本地可执行文件名或绝对路径,不是 shell 命令串。\n * @param args - 逐项传入的参数数组,不再自行拼接 shell。\n * @returns Job 名、隐藏 PowerShell 参数与私有环境载荷。\n * @example 模块内部上下文\n * ```ts\n * const job = windowsCommand(process.execPath, ['--version'])\n * const probe = windowsJobProbe(job.name)\n * // job.args/env 供隐藏 powershell.exe 使用;不要记录其中的私有参数。\n * ```\n */\nexport function windowsCommand(command: string, args: string[]): { name: string, args: string[], env: Record<string, string> } {\n const name = `Local\\\\hai-deploy-${randomUUID()}`\n const key = `__HAI_DEPLOY_JOB_${randomUUID().replaceAll('-', '')}`\n const script = `$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $InformationPreference='SilentlyContinue'\ntry {\n Add-Type -TypeDefinition @'\n${nativeJob}\n'@\n $inputConfig = [Environment]::GetEnvironmentVariable('${key}') | ConvertFrom-Json\n [Environment]::SetEnvironmentVariable('${key}', $null)\n exit ([HaiCommandJob]::Run([string]$inputConfig.name, [string]$inputConfig.command, [string[]]$inputConfig.args))\n} catch { [Console]::Error.WriteLine('Windows command job failed'); exit 125 }`\n return { name, args: powershell(script), env: { [key]: JSON.stringify({ name, command, args }) } }\n}\n\n/**\n * 查询 Job 的真实成员数;不存在表示全部退出,任何检查故障均不能声称终止确认。\n * 名称必须来自 windowsCommand,不能把外部任意文本插入 PowerShell 探测脚本。\n * @param name - 由 windowsCommand 生成的内部 Job 名称。\n * @returns 探测静态脚本的 PowerShell 参数;探测返回码另行检查。\n * @example 模块内部上下文\n * ```ts\n * const job = windowsCommand(process.execPath, ['--version'])\n * const probeArgs = windowsJobProbe(job.name)\n * // 仅对本函数配套创建的 Job 名执行探测;0为空、1仍有成员、2为探测故障。\n * ```\n */\nexport function windowsJobProbe(name: string): string[] {\n return powershell(`$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $InformationPreference='SilentlyContinue'\ntry {\n Add-Type -TypeDefinition @'\n${nativeJob}\n'@\n if ([HaiCommandJob]::Empty('${name}')) { exit 0 } else { exit 1 }\n} catch { exit 2 }`)\n}\n","/** 管理命令的真实本地进程树;POSIX 使用独立进程组,Windows 使用不可 breakaway 的 Job。 */\nimport type { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio } from 'node:child_process'\nimport { spawn } from 'node:child_process'\nimport { readdir, readFile } from 'node:fs/promises'\nimport process from 'node:process'\nimport { setTimeout } from 'node:timers/promises'\nimport { windowsCommand, windowsJobProbe } from './deploy-command-windows.js'\n\n/** Linux 的孤儿 zombie 已退出,不能把未回收的 PID 当作仍执行的进程。 */\nasync function groupExited(pid: number): Promise<boolean> {\n try {\n process.kill(-pid, 0)\n }\n catch (error) {\n return error instanceof Error && 'code' in error && error.code === 'ESRCH'\n }\n if (process.platform !== 'linux')\n return false\n try {\n for (const entry of await readdir('/proc')) {\n if (!/^\\d+$/.test(entry))\n continue\n let stat: string\n try {\n stat = await readFile(`/proc/${entry}/stat`, 'utf8')\n }\n catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT')\n continue\n return false\n }\n // comm 可包含空格/括号,取最后一个右括号之后的固定字段。\n const fields = stat.slice(stat.lastIndexOf(')') + 2).split(' ')\n if (Number(fields[2]) === pid && fields[0] !== 'Z' && fields[0] !== 'X')\n return false\n }\n return true\n }\n catch {\n return false\n }\n}\n\n/** 辅助工具只返回退出码,既不捕获参数/输出,也不把原始错误传播到用户结果。 */\nasync function helper(command: string, args: string[], timeoutMs: number): Promise<boolean> {\n if (timeoutMs <= 0)\n return false\n return new Promise((resolve) => {\n const child = spawn(command, args, { windowsHide: true, shell: false, stdio: 'ignore' })\n let settled = false\n let timer: NodeJS.Timeout | undefined\n const finish = (success: boolean): void => {\n if (settled)\n return\n settled = true\n if (timer)\n clearTimeout(timer)\n resolve(success)\n }\n timer = globalThis.setTimeout(() => {\n child.kill('SIGKILL')\n child.unref()\n finish(false)\n }, timeoutMs)\n child.once('error', () => finish(false))\n child.once('close', code => finish(code === 0))\n })\n}\n\n/**\n * 只向命令执行器暴露必要控制,不把平台句柄或 Job 名称作为用户配置。\n * 控制句柄只管理本地进程树;调用 treeExited/terminate 后仍要按 boolean/状态判断,不推断远端副作用。\n * @example 模块内部上下文\n * ```ts\n * const controlled = spawnCommand(process.execPath, ['--version'], { cwd: process.cwd(), env: process.env })\n * const exited = await controlled.treeExited()\n * if (!exited) {\n * const termination = await controlled.terminate(10000)\n * if (termination === 'unknown') process.stderr.write('Termination unconfirmed\\n')\n * }\n * ```\n */\nexport interface CommandProcess {\n child: ChildProcessWithoutNullStreams\n treeExited: () => Promise<boolean>\n terminate: (timeoutMs: number) => Promise<'confirmed' | 'unknown'>\n}\n\n/**\n * 启动受管理进程;Windows helper/Job 失败时没有裸进程降级路径。\n * 由 runCommand 负责输出、异常与超时编排;此低层入口本身不提供 HaiResult 或脱敏。\n * @param command - 本地可执行文件名或绝对路径,不是 shell 命令串。\n * @param args - 逐项传入的参数数组,不再自行拼接 shell。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 受管理子进程及本地进程树检查/终止句柄。\n * @example 模块内部上下文\n * ```ts\n * const controlled = spawnCommand(process.execPath, ['--version'], { cwd: process.cwd(), env: process.env })\n * const exited = await controlled.treeExited()\n * if (!exited) {\n * const termination = await controlled.terminate(10000)\n * if (termination === 'unknown') process.stderr.write('Termination unconfirmed\\n')\n * }\n * ```\n */\nexport function spawnCommand(command: string, args: string[], options: Pick<SpawnOptionsWithoutStdio, 'cwd' | 'env'>): CommandProcess {\n const job = process.platform === 'win32' ? windowsCommand(command, args) : undefined\n const child = spawn(job ? 'powershell.exe' : command, job?.args ?? args, {\n ...options,\n env: job ? { ...options.env, ...job.env } : options.env,\n windowsHide: true,\n shell: false,\n detached: !job,\n })\n let exited = false\n child.once('exit', () => {\n exited = true\n })\n child.once('close', () => {\n exited = true\n })\n let termination: Promise<'confirmed' | 'unknown'> | undefined\n const treeExited = async (): Promise<boolean> => {\n if (!child.pid)\n return true\n if (job)\n return exited && helper('powershell.exe', windowsJobProbe(job.name), 5000)\n return groupExited(child.pid)\n }\n const terminate = (timeoutMs: number): Promise<'confirmed' | 'unknown'> => {\n termination ??= (async () => {\n const deadline = performance.now() + timeoutMs\n let windowsKillConfirmed = !job || exited\n if (child.pid) {\n if (job) {\n if (!exited) {\n // /T 也覆盖 Add-Type 的编译器;payload 的断链后代由 Job 的 close-kill 保证收回。\n windowsKillConfirmed = await helper('taskkill', ['/pid', String(child.pid), '/t', '/f'], Math.max(1, deadline - performance.now()))\n child.kill('SIGKILL')\n }\n }\n else {\n try {\n process.kill(-child.pid, 'SIGKILL')\n }\n catch {\n // 退出 race 或权限失败都必须由下方状态核验决定,不能把 kill 请求当确认。\n }\n }\n }\n while (performance.now() < deadline) {\n if (exited)\n break\n await setTimeout(20)\n }\n let verified = false\n if (exited && job) {\n // 原生命令已自然返回时,helper 已等待所有 Job 成员;被强杀则仍查询 Job 实际归零。\n verified = await helper('powershell.exe', windowsJobProbe(job.name), deadline - performance.now())\n verified &&= windowsKillConfirmed || child.exitCode !== null\n }\n else if (exited) {\n while (performance.now() < deadline) {\n if (await treeExited()) {\n verified = true\n break\n }\n await setTimeout(20)\n }\n }\n // exit 与管道 close 分开:消费者可仍等待回调,但不能据此误判进程仍运行。\n // 异常后丢弃未完成秘密尾部并关闭管道,不等待无法取消的已进入回调。\n child.stdin.destroy()\n child.stdout.destroy()\n child.stderr.destroy()\n if (!verified)\n child.unref()\n return verified ? 'confirmed' : 'unknown'\n })()\n return termination\n }\n return { child, treeExited, terminate }\n}\n","/** 已知秘密的跨块字面量脱敏;不会把秘密当成正则语法。 */\n\n/**\n * 单个逻辑文本流的脱敏器;UTF-8解码由调用方的StringDecoder完成。\n * @example 模块内部上下文\n * ```ts\n * const masker: SecretMasker = createSecretMasker(['example-token'])\n * const text = masker.write('example-') + masker.write('token public') + masker.end() // *** public\n * ```\n */\nexport interface SecretMasker {\n /** 接收已正确解码的下一块,仅释放不可能与后续块组成秘密的前缀。 */\n write: (text: string) => string\n /** 正常流结束时释放最后一块;重复调用为空,异常终止可丢弃未释放尾部。 */\n end: () => string\n}\n\n/**\n * 创建精确字面量流式脱敏器;最多保留最长秘密长度减一的尾部。\n * 每个逻辑流使用独立实例;write 可能延迟尾部,正常结束须 end,不能提前把缓冲原文输出。\n * @param secrets - 已知敏感值;忽略空值、去重,优先匹配同位置的较长值,总长度上限1Mi UTF-16单元\n * @returns 每次write/end的安全输出按顺序拼接得到完整脱敏文本\n * @throws 秘密总长度超限或底层表达式不能编译时抛错,调用方必须失败关闭\n * @example 模块内部上下文\n * ```ts\n * const masker = createSecretMasker(['example-token'])\n * const output = masker.write('example-') + masker.write('token public') + masker.end() // *** public\n * ```\n */\nexport function createSecretMasker(secrets: readonly string[] = []): SecretMasker {\n const values = [...new Set(secrets.filter(Boolean))].sort((a, b) => b.length - a.length)\n if (values.reduce((total, value) => total + value.length, 0) > 1048576)\n throw new RangeError('Secret redaction input is too large')\n const pattern = values.length ? new RegExp(values.map(value => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|'), 'g') : undefined\n const tailLength = Math.max(0, (values[0]?.length ?? 1) - 1)\n let pending = ''\n let ended = false\n\n /** 在原文边界上计算释放位置;不能从掩码中间切分后再释放其原文尾部。 */\n function drain(final: boolean): string {\n let end = final ? pending.length : Math.max(0, pending.length - tailLength)\n // 避免向分别编码/显示回调片段的消费者交付半个Unicode代理对。\n if (end > 0 && end < pending.length && /[\\uD800-\\uDBFF]/.test(pending[end - 1]!) && /[\\uDC00-\\uDFFF]/.test(pending[end]!))\n end--\n if (end === 0)\n return ''\n let cursor = 0\n let output = ''\n if (pattern) {\n pattern.lastIndex = 0\n let match = pattern.exec(pending)\n while (match && match.index < end) {\n output += `${pending.slice(cursor, match.index)}***`\n cursor = pattern.lastIndex\n // 跨释放边界的完整匹配整体消费,不能在后续write重新暴露其后半段。\n end = Math.max(end, cursor)\n match = pattern.exec(pending)\n }\n }\n output += pending.slice(cursor, end)\n pending = pending.slice(end)\n return output\n }\n\n return {\n write(text) {\n if (ended)\n throw new Error('Secret masker has ended')\n pending += text\n return drain(false)\n },\n end() {\n if (ended)\n return ''\n ended = true\n return drain(true)\n },\n }\n}\n","/**\n * @h-ai/deploy — 命令执行器。\n * command与args分离,不经过shell;流式回调、捕获结果和错误使用相同秘密脱敏边界。\n * @module deploy-command\n */\nimport type { HaiResult } from '@h-ai/core'\nimport type { DeployCommandState } from '../deploy-types.js'\nimport process from 'node:process'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { spawnCommand } from './deploy-command-process.js'\nimport { createSecretMasker } from './deploy-secret-masker.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'command' })\n\n/**\n * 命令执行选项;secrets必须列出可能输出的已知敏感值。\n * @example 模块内部上下文\n * ```ts\n * const options: CommandOptions = { cwd: process.cwd(), timeoutMs: 5000, terminationTimeoutMs: 10000, maxCaptureChars: 4096 }\n * const result = await runCommand(process.execPath, ['--version'], options)\n * if (!result.success) throw new Error(result.error.message)\n * ```\n */\nexport interface CommandOptions {\n /** 正确UTF-8解码且跨块脱敏的stdout片段;顺序完整,末尾可能延迟至close。 */\n onOutput?: (output: string) => void | Promise<void>\n /** 工作目录。 */\n cwd?: string\n /** 追加环境;不会自动将全部环境值视为秘密。 */\n env?: Record<string, string>\n /** 超时毫秒,须为 1..2147483647 的整数;超时不代表远程进程已终止。 */\n timeoutMs?: number\n /** 超时/异常后核验本地树退出的最长等待,默认 10 秒,最大 60 秒;未确认时返回 unknown。 */\n terminationTimeoutMs?: number\n /** 通过stdin传入的内容。 */\n input?: string\n /** 已知敏感字面量;总长度最多1Mi UTF-16单元,超限失败关闭。 */\n secrets?: string[]\n /** 每条捕获流保留的尾部字符上限,默认1Mi,最大16Mi;回调仍接收全部安全stdout。 */\n maxCaptureChars?: number\n}\n\n/**\n * 已脱敏的有界命令结果;解析结构化输出前必须拒绝截断结果。\n * 仅保存脱敏流的有界尾部;不把尾部捕获当作完整日志。\n * @example 模块内部上下文\n * ```ts\n * const result = await runCommand(process.execPath, ['--version'], { maxCaptureChars: 4096 })\n * if (!result.success) throw new Error(result.error.message)\n * const output: CommandResult = result.data\n * const truncated = output.stdoutTruncated\n * ```\n */\nexport interface CommandResult {\n /** 实际退出码。 */\n code: number\n /** 已脱敏stdout尾部。 */\n stdout: string\n /** 已脱敏stderr尾部。 */\n stderr: string\n /** stdout是否超过捕获上限。 */\n stdoutTruncated: boolean\n /** stderr是否超过捕获上限。 */\n stderrTruncated: boolean\n}\n\n/**\n * 对完整文本进行同样的精确字面量脱敏。\n * @param text - 完整文本\n * @param secrets - 已知秘密\n * @returns 脱敏文本\n * @example 模块内部上下文\n * ```ts\n * const text = maskSecrets('example-token public', ['example-token']) // *** public;合成字符串只用于演示。\n * ```\n */\nexport function maskSecrets(text: string, secrets: string[] = []): string {\n const masker = createSecretMasker(secrets)\n return masker.write(text) + masker.end()\n}\n\n/**\n * 执行外部命令,捕获与回调在UTF-8解码后以逻辑流为单位脱敏。\n * 无 shell 启动命令;stdout 回调接收按顺序脱敏的完整流,捕获结果仅保留有界尾部。超时后核验本地树退出;SSH 的远端状态由上层单独核对。\n * @param command - 可执行文件名或路径,不使用shell\n * @param args - 独立参数\n * @param options - 超时、输入、已知秘密及安全输出选项\n * @returns 失败返回REMOTE_COMMAND_FAILED;ext.commandExecution 记录终止核验,不暴露原始异常cause\n * @example 模块内部上下文\n * ```ts\n * const result = await runCommand(process.execPath, ['--version'], { timeoutMs: 5000, maxCaptureChars: 4096 })\n * if (!result.success) {\n * const { getDeployCommandState } = await import('../deploy-recovery.js')\n * const state = getDeployCommandState(result.error)\n * if (state?.localTermination === 'unknown') process.stderr.write('Local process-tree exit was not confirmed\\n')\n * }\n * else {\n * const output = result.data.stdout\n * }\n * ```\n */\nexport async function runCommand(command: string, args: string[], options: CommandOptions = {}): Promise<HaiResult<CommandResult>> {\n /** 失败状态只包含核验结论,不附加原始异常或可能携密的命令参数。 */\n const failure = (message: string, state: DeployCommandState): HaiResult<never> => err({\n ...HaiDeployError.REMOTE_COMMAND_FAILED,\n message: `${message}\\n${deployM(state.localTermination === 'confirmed' ? 'deploy_localStopped' : state.localTermination === 'not-started' ? 'deploy_localNotStarted' : 'deploy_localUnknown')}`,\n ext: { commandExecution: state },\n })\n try {\n return await new Promise((resolve) => {\n if (typeof command !== 'string' || !command || command.includes('\\0') || args.some(argument => typeof argument !== 'string' || argument.includes('\\0')))\n throw new TypeError('Invalid command arguments')\n if (options.input !== undefined && typeof options.input !== 'string')\n throw new TypeError('Invalid command input')\n const maxCapture = options.maxCaptureChars ?? 1048576\n if (!Number.isSafeInteger(maxCapture) || maxCapture <= 0 || maxCapture > 16777216)\n throw new RangeError('Invalid command capture limit')\n const terminationTimeout = options.terminationTimeoutMs ?? 10_000\n if (!Number.isSafeInteger(terminationTimeout) || terminationTimeout <= 0 || terminationTimeout > 60_000)\n throw new RangeError('Invalid command termination timeout')\n if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > 2147483647))\n throw new RangeError('Invalid command timeout')\n const secrets = [...(options.secrets ?? [])]\n const safeCommand = maskSecrets(command, secrets)\n const outputMasker = createSecretMasker(secrets)\n const errorMasker = createSecretMasker(secrets)\n const control = spawnCommand(command, args, { cwd: options.cwd, env: options.env ? { ...process.env, ...options.env } : process.env })\n const child = control.child\n child.stdout.setEncoding('utf8')\n child.stderr.setEncoding('utf8')\n let stdout = ''\n let stderr = ''\n let stdoutTruncated = false\n let stderrTruncated = false\n let settled = false\n let interrupted = false\n let interruption: Promise<void> | undefined\n let timer: NodeJS.Timeout | undefined\n const finish = (result: HaiResult<CommandResult>): void => {\n if (settled)\n return\n settled = true\n if (timer)\n clearTimeout(timer)\n resolve(result)\n }\n /** 先停止输出交付,再终止并等待整棵树;同一失败/close race 只结束一次。 */\n const interrupt = (reason: DeployCommandState['reason'], message: string): Promise<void> => {\n interrupted = true\n interruption ??= (async () => {\n if (timer)\n clearTimeout(timer)\n const localTermination = child.pid ? await control.terminate(terminationTimeout) : 'not-started'\n logger.error('Command termination checked', { command: safeCommand, reason, localTermination })\n finish(failure(message, { reason, localTermination }))\n })()\n return interruption\n }\n /** 所有捕获发生在脱敏后;流尾部状态和捕获长度均有上限。 */\n const publish = async (text: string): Promise<void> => {\n if (!text || settled || interrupted)\n return\n stdoutTruncated ||= stdout.length + text.length > maxCapture\n stdout = (stdout + text).slice(-maxCapture)\n try {\n await options.onOutput?.(text)\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n }\n const captureError = (text: string): void => {\n stderrTruncated ||= stderr.length + text.length > maxCapture\n stderr = (stderr + text).slice(-maxCapture)\n }\n if (options.timeoutMs && options.timeoutMs > 0) {\n timer = setTimeout(() => {\n logger.error('Command timed out', { command: safeCommand, timeoutMs: options.timeoutMs })\n // 异常结束不释放可能尚未完整的秘密尾部,也不再调用onOutput。\n void interrupt('timeout', deployM('deploy_commandTimeout', { params: { command: safeCommand } }))\n }, options.timeoutMs)\n }\n // 异步迭代器在等待回调期间保留pipe背压,不创建无限增长的Promise/输出队列。\n const outputTask = (async () => {\n try {\n for await (const chunk of child.stdout as AsyncIterable<unknown>) {\n if (settled || interrupted)\n return\n if (typeof chunk !== 'string')\n throw new TypeError('Command output must be UTF-8 decoded')\n await publish(outputMasker.write(chunk))\n }\n if (!settled && !interrupted)\n await publish(outputMasker.end())\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n })()\n const errorTask = (async () => {\n try {\n for await (const chunk of child.stderr as AsyncIterable<unknown>) {\n if (settled || interrupted)\n return\n if (typeof chunk !== 'string')\n throw new TypeError('Command error output must be UTF-8 decoded')\n captureError(errorMasker.write(chunk))\n }\n if (!settled && !interrupted)\n captureError(errorMasker.end())\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n })()\n child.stdin.on('error', () => {\n void interrupt('input', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandInputFailed') } }))\n })\n child.on('error', (error) => {\n const safeError = maskSecrets(error.message, secrets)\n logger.error('Command failed to start', { command: safeCommand, error: safeError })\n void interrupt('spawn', deployM('deploy_commandFailed', { params: { command: safeCommand, error: safeError } }))\n })\n child.on('close', async (code) => {\n await Promise.all([outputTask, errorTask])\n if (settled || interrupted)\n return\n if (timer)\n clearTimeout(timer)\n if (!(await control.treeExited())) {\n await interrupt('exit', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandTreeActive') } }))\n return\n }\n const exitCode = code ?? -1\n if (exitCode === 0) {\n finish(ok({ code: exitCode, stdout, stderr, stdoutTruncated, stderrTruncated }))\n return\n }\n logger.error('Command exited with non-zero code', { command: safeCommand, code: exitCode, stderr: maskSecrets(stderr, secrets).slice(-500), stdout: maskSecrets(stdout, secrets).slice(-3000), stdoutTruncated, stderrTruncated })\n finish(failure(deployM('deploy_commandFailed', { params: { command: safeCommand, error: maskSecrets(`${stdout.slice(-2500)}\\n${stderr || `exit ${exitCode}`}`, secrets).slice(-3000) } }), { reason: 'exit', localTermination: 'confirmed' }))\n })\n if (options.input !== undefined)\n child.stdin.write(options.input)\n child.stdin.end()\n })\n }\n catch {\n // 参数/正则编译/spawn同步错误可能携带原秘密,使用无cause的固定诊断失败关闭。\n return failure(deployM('deploy_commandFailed', { params: { command: '<command>', error: deployM('deploy_commandExecutionFailed') } }), { reason: 'configuration', localTermination: 'not-started' })\n }\n}\n","/** OpenSSH 的私有 askpass;固定 helper 无密码,凭据只在本次受管理子进程环境中存在。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { chmodSync, existsSync, lstatSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { runCommand } from './deploy-command.js'\n\n/**\n * 固定 C# 程序仅从环境读取密码,不含编译期或持久化凭据。\n * @example 模块内部上下文\n * ```ts\n * // sourceFile 由调用方在本次私有临时目录中分配;只落盘固定源码。\n * function writeWindowsSource(sourceFile: string): void {\n * writeFileSync(sourceFile, windowsAskpassSource, { mode: 0o600 })\n * }\n * ```\n */\nexport const windowsAskpassSource = String.raw`using System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Text;\nusing System.Threading;\npublic static class HaiDeployAskpass {\n public static int Main(string[] args) {\n if (args.Length >= 2 && args[0] == \"--run\") return Run(args);\n if (Environment.GetEnvironmentVariable(\"SSH_ASKPASS_PROMPT\") == \"confirm\") return 1;\n string value = Environment.GetEnvironmentVariable(\"HAI_DEPLOY_ASKPASS_PASSWORD\");\n if (String.IsNullOrEmpty(value) || value.IndexOfAny(new char[] { '\\r', '\\n', '\\0' }) >= 0 || Encoding.UTF8.GetByteCount(value) > 1023) return 1;\n Console.OutputEncoding = new UTF8Encoding(false);\n Console.Out.Write(value);\n Console.Out.Write(\"\\n\");\n return 0;\n }\n static string Quote(string value) {\n StringBuilder text = new StringBuilder(\"\\\"\");\n int slashes = 0;\n foreach (char character in value) {\n if (character == '\\\\') { slashes++; continue; }\n if (character == '\"') { text.Append('\\\\', slashes * 2 + 1).Append(character); slashes = 0; continue; }\n text.Append('\\\\', slashes).Append(character); slashes = 0;\n }\n return text.Append('\\\\', slashes * 2).Append('\"').ToString();\n }\n static void Pump(TextReader input, TextWriter output, string secret) {\n char[] buffer = new char[4096];\n StringBuilder pending = new StringBuilder();\n int count;\n while ((count = input.Read(buffer, 0, buffer.Length)) > 0) {\n pending.Append(buffer, 0, count);\n while (pending.Length >= secret.Length) {\n bool matches = true;\n for (int i = 0; i < secret.Length; i++) if (pending[i] != secret[i]) { matches = false; break; }\n if (matches) { output.Write(\"***\"); pending.Remove(0, secret.Length); }\n else { output.Write(pending[0]); pending.Remove(0, 1); }\n }\n output.Flush();\n }\n output.Write(pending.ToString()); output.Flush();\n }\n static int Run(string[] args) {\n try {\n string secret = Environment.GetEnvironmentVariable(\"HAI_DEPLOY_ASKPASS_PASSWORD\");\n if (String.IsNullOrEmpty(secret)) return 1;\n ProcessStartInfo start = new ProcessStartInfo();\n start.FileName = args[1]; start.UseShellExecute = false; start.CreateNoWindow = true;\n start.RedirectStandardOutput = true; start.RedirectStandardError = true;\n start.StandardOutputEncoding = new UTF8Encoding(false); start.StandardErrorEncoding = new UTF8Encoding(false);\n StringBuilder arguments = new StringBuilder();\n for (int i = 2; i < args.Length; i++) { if (i > 2) arguments.Append(' '); arguments.Append(Quote(args[i])); }\n start.Arguments = arguments.ToString();\n using (Process child = Process.Start(start)) {\n Thread stdout = new Thread(() => Pump(child.StandardOutput, Console.Out, secret));\n Thread stderr = new Thread(() => Pump(child.StandardError, Console.Error, secret));\n stdout.Start(); stderr.Start(); child.WaitForExit(); stdout.Join(); stderr.Join(); return child.ExitCode;\n }\n } catch { Console.Error.WriteLine(\"SSH command failed.\"); return 1; }\n }\n}\n`\n\n/**\n * POSIX helper 只输出环境原值;主机信任确认不应由密码代答。\n * @example 模块内部上下文\n * ```ts\n * // helperFile 位于本次私有临时目录;密码由执行时的 child env 提供。\n * function writePosixHelper(helperFile: string): void {\n * writeFileSync(helperFile, posixAskpassSource, { mode: 0o700 })\n * }\n * ```\n */\nexport const posixAskpassSource = String.raw`#!/bin/sh\ntest \"\\${SSH_ASKPASS_PROMPT:-}\" != confirm || exit 1\ntest -n \"\\${HAI_DEPLOY_ASKPASS_PASSWORD:-}\" || exit 1\nprintf '%s\\n' \"$HAI_DEPLOY_ASKPASS_PASSWORD\"\n`.replaceAll('\\\\${', '${')\n\n/**\n * Windows PowerShell 5/.NET Framework 编译;不使用不支持原生 ConsoleApplication 的 pwsh。\n * @example 模块内部上下文\n * ```ts\n * // compiler 是系统 Windows PowerShell 5;两个文件路径均由本次私有目录分配。\n * async function compileHelper(compiler: string, sourceFile: string, outputFile: string) {\n * const compiled = await runCommand(compiler, ['-NoProfile', '-NonInteractive', '-Command', compileAskpassScript], {\n * env: { HAI_DEPLOY_ASKPASS_SOURCE: sourceFile, HAI_DEPLOY_ASKPASS_OUTPUT: outputFile, HAI_DEPLOY_ASKPASS_PASSWORD: '' },\n * timeoutMs: 30000,\n * })\n * if (!compiled.success) return compiled\n * return ok(undefined)\n * }\n * ```\n */\nexport const compileAskpassScript = '$ErrorActionPreference=\\'Stop\\'; Add-Type -Language CSharp -TypeDefinition ([System.IO.File]::ReadAllText($env:HAI_DEPLOY_ASKPASS_SOURCE, [System.Text.Encoding]::UTF8)) -OutputType ConsoleApplication -OutputAssembly $env:HAI_DEPLOY_ASKPASS_OUTPUT'\n\n/**\n * 本次 helper 的受控环境与清理操作;目录只属于当前命令调用。\n * @example 模块内部上下文\n * ```ts\n * function finishHelper(helper: SshAskpass): HaiResult<void> {\n * const removed = helper.cleanup()\n * if (!removed.success) return removed\n * return ok(undefined)\n * }\n * ```\n */\nexport interface SshAskpass {\n env: Record<string, string>\n cleanup: () => HaiResult<void>\n}\n\n/** 不传播可能包含输入的异常;本地准备失败尚未开始 SSH 远端操作。 */\nfunction helperFailure(key: 'deploy_sshAskpassFailed' | 'deploy_sshAskpassCleanupFailed', reason: 'configuration' | 'timeout' = 'configuration'): HaiResult<never> {\n return err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM(key), ext: { commandExecution: { reason, localTermination: 'not-started' } } })\n}\n\n/**\n * 为一次命令准备无秘密 helper;准备时间包含在调用者的绝对单调时钟 deadline 内。\n * @param password - 已校验、保持空格和 Unicode 的密码原值。\n * @param deadline - performance.now() 的绝对毫秒期限;Infinity 表示命令没有整体期限。\n * @param terminationTimeoutMs - 原受管理进程树终止核验预算。\n * @returns 固定 helper 环境及清理函数;失败不暴露原异常或降级交互输入。\n * @example 模块内部上下文\n * ```ts\n * async function inspectPreparedHelper(password: string) {\n * const prepared = await prepareSshAskpass(password, performance.now() + 20000)\n * if (!prepared.success) return prepared\n * const askpassMode = prepared.data.env.SSH_ASKPASS_REQUIRE\n * const removed = prepared.data.cleanup()\n * if (!removed.success) return removed\n * return ok(askpassMode)\n * }\n * ```\n */\nexport async function prepareSshAskpass(password: string, deadline: number, terminationTimeoutMs?: number): Promise<HaiResult<SshAskpass>> {\n let directory: string | undefined\n let temporaryRoot: string | undefined\n const cleanup = (): HaiResult<void> => {\n if (!directory || !existsSync(directory))\n return ok(undefined)\n try {\n if (lstatSync(directory).isSymbolicLink() || dirname(realpathSync(directory)) !== temporaryRoot || !basename(directory).startsWith('hai-ssh-askpass-'))\n return helperFailure('deploy_sshAskpassCleanupFailed')\n rmSync(directory, { recursive: true, force: false })\n return ok(undefined)\n }\n catch { return helperFailure('deploy_sshAskpassCleanupFailed') }\n }\n try {\n temporaryRoot = realpathSync(tmpdir())\n if (deadline <= performance.now())\n return helperFailure('deploy_sshAskpassFailed', 'timeout')\n if (!password || /[\\r\\n\\0]/.test(password) || new TextEncoder().encode(password).length > 1023)\n return helperFailure('deploy_sshAskpassFailed')\n directory = mkdtempSync(join(temporaryRoot, 'hai-ssh-askpass-'))\n chmodSync(directory, 0o700)\n let helper = join(directory, 'askpass.sh')\n if (process.platform === 'win32') {\n helper = join(directory, 'askpass.exe')\n const source = join(directory, 'askpass.cs')\n writeFileSync(source, windowsAskpassSource, { mode: 0o600 })\n const compiler = join(process.env.SystemRoot ?? 'C:\\\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')\n const compiled = await runCommand(compiler, ['-NoProfile', '-NonInteractive', '-Command', compileAskpassScript], {\n env: { HAI_DEPLOY_ASKPASS_SOURCE: source, HAI_DEPLOY_ASKPASS_OUTPUT: helper, HAI_DEPLOY_ASKPASS_PASSWORD: '' },\n timeoutMs: Math.max(1, Math.min(30_000, Math.ceil(deadline - performance.now()))),\n terminationTimeoutMs,\n secrets: [password],\n })\n if (!compiled.success) {\n const removed = cleanup()\n return removed.success ? compiled : removed\n }\n if (!existsSync(helper)) {\n const removed = cleanup()\n return removed.success ? helperFailure('deploy_sshAskpassFailed') : removed\n }\n }\n else {\n writeFileSync(helper, posixAskpassSource, { mode: 0o700 })\n }\n if (deadline <= performance.now()) {\n const removed = cleanup()\n return removed.success ? helperFailure('deploy_sshAskpassFailed', 'timeout') : removed\n }\n return ok({ env: { SSH_ASKPASS: helper, SSH_ASKPASS_REQUIRE: 'force', SSH_ASKPASS_PROMPT: '', DISPLAY: 'hai-deploy:0', HAI_DEPLOY_ASKPASS_PASSWORD: password }, cleanup })\n }\n catch {\n const removed = cleanup()\n return removed.success ? helperFailure('deploy_sshAskpassFailed') : removed\n }\n}\n","/**\n * 生成独立 JSON 读取器;上传脚本仅需 POSIX awk,无 Node 或 jq 依赖。\n * @returns 可作为部署包 read-target.awk 文件内容的 POSIX awk 程序。\n * @example 模块内部上下文\n * ```ts\n * const reader: string = createTargetReader()\n * // 将 reader 写入部署包,由上传脚本读取 deploy-target.json 中的目标配置。\n * ```\n */\nexport function createTargetReader(): string {\n return String.raw`function fail(message) {\n print \"Invalid deploy-target.json: \" message > \"/dev/stderr\"\n exit 2\n}\nfunction whitespace() {\n while (substr(input, position, 1) ~ /^[ \\t\\r\\n]$/) position++\n}\nfunction hexadecimal(text, result, offset, digit) {\n result = 0\n if (length(text) != 4) fail(\"invalid Unicode escape\")\n for (offset = 1; offset <= 4; offset++) {\n digit = index(\"0123456789abcdef\", tolower(substr(text, offset, 1))) - 1\n if (digit < 0) fail(\"invalid Unicode escape\")\n result = result * 16 + digit\n }\n return result\n}\nfunction utf8(code) {\n if (code < 128) return sprintf(\"%c\", code)\n if (code < 2048) return sprintf(\"%c%c\", 192 + int(code / 64), 128 + code % 64)\n if (code < 65536) return sprintf(\"%c%c%c\", 224 + int(code / 4096), 128 + int(code / 64) % 64, 128 + code % 64)\n return sprintf(\"%c%c%c%c\", 240 + int(code / 262144), 128 + int(code / 4096) % 64, 128 + int(code / 64) % 64, 128 + code % 64)\n}\nfunction string_value( result, character, escaped, code, low) {\n if (substr(input, position++, 1) != \"\\\"\") fail(\"expected string\")\n result = \"\"\n while (position <= length(input)) {\n character = substr(input, position++, 1)\n if (character == \"\\\"\") return result\n if (character ~ /[[:cntrl:]]/) fail(\"control character in string\")\n if (character != \"\\\\\") { result = result character; continue }\n escaped = substr(input, position++, 1)\n if (escaped == \"\\\"\" || escaped == \"\\\\\" || escaped == \"/\") result = result escaped\n else if (escaped == \"b\") result = result sprintf(\"%c\", 8)\n else if (escaped == \"f\") result = result sprintf(\"%c\", 12)\n else if (escaped == \"n\") result = result \"\\n\"\n else if (escaped == \"r\") result = result \"\\r\"\n else if (escaped == \"t\") result = result \"\\t\"\n else if (escaped == \"u\") {\n code = hexadecimal(substr(input, position, 4)); position += 4\n if (code >= 55296 && code <= 56319) {\n if (substr(input, position, 2) != \"\\\\u\") fail(\"missing low surrogate\")\n position += 2\n low = hexadecimal(substr(input, position, 4)); position += 4\n if (low < 56320 || low > 57343) fail(\"invalid low surrogate\")\n code = 65536 + (code - 55296) * 1024 + low - 56320\n } else if (code >= 56320 && code <= 57343) fail(\"unexpected low surrogate\")\n if (code == 0) fail(\"NUL is not allowed\")\n result = result utf8(code)\n } else fail(\"invalid escape\")\n }\n fail(\"unterminated string\")\n}\nfunction object_value(depth, key, character, value, kind) {\n if (depth > 16) fail(\"nesting is too deep\")\n position++\n whitespace()\n if (substr(input, position, 1) == \"}\") { position++; return }\n while (position <= length(input)) {\n whitespace(); key = string_value(); whitespace()\n if (substr(input, position++, 1) != \":\") fail(\"expected colon\")\n whitespace(); character = substr(input, position, 1)\n if (character == \"{\") { object_value(depth + 1); value = \"\"; kind = \"object\" }\n else if (character == \"\\\"\") { value = string_value(); kind = \"string\" }\n else if (substr(input, position, 4) == \"true\") { value = \"true\"; kind = \"boolean\"; position += 4 }\n else if (substr(input, position, 5) == \"false\") { value = \"false\"; kind = \"boolean\"; position += 5 }\n else if (substr(input, position, 4) == \"null\") { value = \"\"; kind = \"null\"; position += 4 }\n else if (match(substr(input, position), /^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?/)) {\n value = substr(input, position, RLENGTH); position += RLENGTH; kind = \"number\"\n } else fail(\"unsupported value\")\n if (depth == 1) {\n if (key in values) fail(\"duplicate field: \" key)\n values[key] = value; kinds[key] = kind\n }\n whitespace(); character = substr(input, position++, 1)\n if (character == \"}\") return\n if (character != \",\") fail(\"expected comma or closing brace\")\n }\n fail(\"unterminated object\")\n}\n{ input = input $0 \"\\n\" }\nEND {\n position = 1\n if (substr(input, 1, 3) == sprintf(\"%c%c%c\", 239, 187, 191)) position = 4\n whitespace()\n if (substr(input, position, 1) != \"{\") fail(\"expected object\")\n object_value(1); whitespace()\n if (position <= length(input)) fail(\"trailing content\")\n if (!(field in values) || kinds[field] == \"null\") { print fallback; exit }\n if (kinds[field] != expected) fail(\"wrong type for \" field)\n if (values[field] ~ /[[:cntrl:]]/) fail(\"control character in \" field)\n print values[field]\n}\n`\n}\n","/** 在线发布与手工交付共用的服务器执行脚本。远程依赖 Linux flock、基础工具及 Compose。 */\nimport { deployM } from '../deploy-i18n.js'\nimport { createComposeContainerLookupScript } from './deploy-compose-identity.js'\nimport { windowsAskpassSource } from './deploy-ssh-askpass.js'\nimport { createTargetReader } from './deploy-target.js'\n\n/**\n * 将可信配置编码为一个 shell 参数。\n * @param value - 受信值,编码为一个远端 shell 参数。\n * @returns 可作为一个远端 shell 参数的编码文本。\n * @example 模块内部上下文\n * ```ts\n * const encoded = shellArgument(\"Shop's app\") // 整体作为一个远端 shell 参数。\n * ```\n */\nexport function shellArgument(value: string): string {\n return `'${value.replaceAll('\\'', '\\'\"\\'\"\\'')}'`\n}\n\n/**\n * 生成分步执行、增量合并和失败恢复脚本;密钥始终从环境文件读取。\n * 仅生成 Linux 脚本;正常收尾显式释放 FD9 flock,中断时由仍持有描述符的进程树维持。未知旧锁目录不删除,结果仅由取得锁的 owner 发布。\n * @param options - 本次操作选项;字段含义见各子项。\n * @param options.deploymentId - 本次不可变部署标识,用于结果匹配和发布目录。\n * @param options.projectName - 已归一化的项目名称。\n * @param options.environment - 部署环境标识,通常为 prod。\n * @param options.directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @param options.runtime - 容器引擎策略;auto 探测可用引擎并优先 Podman。\n * @param options.partial - 是否为增量服务部署;不能据此执行首次全量安装。\n * @param options.selected - 本次选择更新的 Compose 服务。\n * @param options.hostPort - 宿主公开端口。\n * @param options.healthPaths - 允许执行的应用健康检查路径。\n * @param options.primaryService - 主运行服务角色,用于定位私有运行环境与启动提示。\n * @returns 待在 Linux 远端运行的 apply 脚本文本。\n * @example 模块内部上下文\n * ```ts\n * const script = createApplyScript({ deploymentId: 'shop-prod-001', projectName: 'shop-prod', environment: 'prod', directory: '/opt/hai/apps/shop-prod', runtime: 'auto', partial: false, selected: ['serv'], hostPort: 8080, healthPaths: ['/health'] })\n * ```\n */\nexport function createApplyScript(options: {\n deploymentId: string\n projectName: string\n environment: string\n directory: string\n runtime: 'auto' | 'docker' | 'podman'\n partial: boolean\n selected: string[]\n hostPort: number\n healthPaths: string[]\n primaryService?: 'serv' | 'web'\n}): string {\n const values: Record<string, string> = {\n ID: shellArgument(options.deploymentId),\n PROJECT: shellArgument(`hai-${options.projectName}`),\n ENV: shellArgument(options.environment),\n RUNTIME: shellArgument(options.runtime),\n PARTIAL: options.partial ? 'true' : 'false',\n SELECTED: shellArgument(options.selected.join(' ')),\n ROOT: shellArgument(options.directory),\n PORT: String(options.hostPort),\n HEALTH: options.healthPaths.map(shellArgument).join(' '),\n PRIMARY: options.primaryService ?? 'serv',\n LOOKUP: createComposeContainerLookupScript(),\n }\n return String.raw`#!/bin/sh\n# 服务器部署流程:由 deploy-local.sh 或 SSH 入口自动解包后调用,无需手工解包。\n# 需要 Linux、sha256sum、tar、awk、curl、flock 和可用的 Docker/Podman Compose;不会联网拉镜像。\n# 本次全量/增量及服务清单由生成时的 manifest.json 和下方 partial/selected 固定。\n# 增量要求服务器已有成功的全量基线;校验失败不会开始替换服务,失败恢复保留数据卷。\nset -eu\numask 077\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\ndestination=@@ROOT@@\nif [ \"$#\" -gt 0 ]; then destination=$1; fi\nroot=$(mkdir -p -- \"$destination\" && CDPATH= cd -- \"$destination\" && pwd)\nid=@@ID@@\nproject=@@PROJECT@@\nexport HAI_DEPLOY_ENVIRONMENT=@@ENV@@\nruntime=@@RUNTIME@@\npartial=@@PARTIAL@@\norphan_option=''\nif [ \"$partial\" = false ]; then orphan_option=--remove-orphans; fi\nrecreate_option=--force-recreate\nif [ \"$partial\" = true ]; then recreate_option=--no-recreate; fi\nselected=@@SELECTED@@\nproxy_update=false\nrelease=\"$root/releases/$id\"\ncase \"$release/\" in \"$source_dir/\"*) printf 'Extract the package outside the deployment directory before applying it.\\n' >&2; exit 1;; esac\nstage=''\nprevious=''\nrestore=''\nchanged=false\nimages_changed=false\nrecovery_status=not-needed\nlocked=false\nresult_owned=false\ninterrupted=false\nstarted=$(date +%s)\nstep_started=$started\n@@LOOKUP@@\nstep() {\n if [ -n \"$stage\" ] && [ \"$result_owned\" = true ]; then\n duration=$(( $(date +%s) - step_started ))\n printf '[PASS] %s (%ss)\\n' \"$stage\" \"$duration\"\n printf '{\"stage\":\"%s\",\"status\":\"passed\",\"durationSeconds\":%s}\\n' \"$stage\" \"$duration\" >> \"$root/steps-$id.jsonl\"\n fi\n stage=\"$1\"\n step_started=$(date +%s)\n printf '\\n[%s] %s\\n' \"$stage\" \"$2\"\n}\ncompose() {\n arguments_file=\"$release/compose-files\"\n if [ -n \"$restore\" ]; then arguments_file=\"$root/releases/$restore/compose-files\"; fi\n # -f 按顺序合并,由 Compose 保留未选服务、卷和环境文件,不自行拼装配置。\n command_args=\"$release/.compose-command\"\n # 文件列表先反向读取,再向参数头部加入,保留原始合并顺序。\n awk '{lines[NR]=$0} END {for(i=NR;i>0;i--) print lines[i]}' \"$arguments_file\" > \"$command_args\"\n while IFS= read -r file; do set -- -f \"$file\" \"$@\"; done < \"$command_args\"\n \"$runtime\" compose -p \"$project\" \"$@\"\n}\nremove_selected() {\n test \"$partial\" = true || return 0\n # 直接替换选中容器,避免 Compose Provider 连带重建依赖它的未选服务;不删除卷。\n for service in \"$@\"; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -aq) || return 1\n for container in $containers; do\n \"$runtime\" rm -f \"$container\" || return 1\n done\n done\n}\nwait_services() {\n for waiting_service in \"$@\"; do\n ready=false\n attempt=0\n while [ \"$attempt\" -lt 60 ]; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$waiting_service\" -q) || return 1\n test -n \"$containers\" || { printf 'Service %s is not running. Inspect its startup diagnostics.\\n' \"$waiting_service\" >&2; return 1; }\n ready=true\n for container in $containers; do\n running=$(\"$runtime\" inspect --format '{{.State.Running}}' \"$container\") || return 1\n test \"$running\" = true || { printf 'Service %s stopped during startup.\\n' \"$waiting_service\" >&2; return 1; }\n health=$(\"$runtime\" inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' \"$container\") || return 1\n # 独立 Podman 可能没有 systemd 调度;主动探测后重读状态,失败不能放行业务。\n case \"$runtime:$health\" in\n podman:starting|podman:unhealthy|podman:healthy)\n probe_ready=false\n if \"$runtime\" healthcheck run \"$container\" >/dev/null 2>&1; then probe_ready=true; fi\n health=$(\"$runtime\" inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' \"$container\") || return 1\n # 当前探测失败不能依赖旧 healthy 状态放行。\n if [ \"$probe_ready\" != true ] && [ \"$health\" = healthy ]; then health=starting; fi\n ;;\n esac\n case \"$health\" in\n healthy|none) ;;\n unhealthy) printf 'Service %s is unhealthy. Inspect its startup diagnostics.\\n' \"$waiting_service\" >&2; return 1;;\n *) ready=false;;\n esac\n done\n if [ \"$ready\" = true ]; then break; fi\n attempt=$((attempt + 1))\n sleep 2\n done\n test \"$ready\" = true || { printf 'Service %s did not become ready before the startup deadline.\\n' \"$waiting_service\" >&2; return 1; }\n done\n}\nstart_services() {\n middleware_services=''\n application_services=''\n application_orphan_option=$orphan_option\n for service in \"$@\"; do\n case \"$service\" in serv|web|gateway|certbot) ;; *) middleware_services=\"$middleware_services $service\";; esac\n done\n if [ -n \"$middleware_services\" ]; then\n compose up -d --no-deps --no-build --pull never \"$recreate_option\" $orphan_option $middleware_services || return 1\n wait_services $middleware_services || return 1\n # Podman Compose 按本批服务清理孤立容器;后批不能删除已经就绪的中间件。\n application_orphan_option=''\n fi\n # --no-deps 保留未选容器;先等本次中间件就绪,再启动应用和依赖它的 Web。\n case \" $* \" in *' serv '*) application_services=serv;; esac\n case \" $* \" in *' web '*) application_services=\"$application_services web\";; esac\n if [ -n \"$application_services\" ]; then\n compose up -d --no-deps --no-build --pull never \"$recreate_option\" $application_orphan_option $application_services || return 1\n fi\n case \" $* \" in *' gateway '*) compose up -d --no-deps --no-build --pull never \"$recreate_option\" gateway || return 1;; esac\n}\nstart_renewal() {\n case \" $* \" in *' certbot '*) compose up -d --no-deps --no-build --pull never --no-recreate certbot || return 1;; esac\n}\nread_proxy_service() {\n proxy_directory=$1\n if [ -e \"$proxy_directory/proxy-service\" ] || [ -L \"$proxy_directory/proxy-service\" ]; then\n test -f \"$proxy_directory/proxy-service\" && test ! -L \"$proxy_directory/proxy-service\" || return 1\n stored_proxy=$(cat \"$proxy_directory/proxy-service\") || return 1\n else\n stored_proxy=$(awk -F: 'NR == 1 { if ($3 == \"true\") print \"web\"; else if ($3 == \"gateway\") print \"gateway\"; }' \"$proxy_directory/layout\") || return 1\n fi\n case \"$stored_proxy\" in ''|web|gateway) printf '%s' \"$stored_proxy\";; *) return 1;; esac\n}\nreload_retained_proxy() {\n retained_proxy=$(read_proxy_service \"$1\") || return 1\n test -n \"$retained_proxy\" || return 0\n # Nginx 静态 upstream 会保留旧容器 IP;应用或存储增量替换后重新解析服务 DNS。\n case \" $selected \" in *' serv '*|*' web '*|*' storage '*)\n case \" $selected \" in *\" $retained_proxy \"*) ;; *)\n if grep -qx \"$retained_proxy\" \"$1/services\"; then compose exec -T \"$retained_proxy\" nginx -s reload || return 1; fi\n ;;\n esac\n ;;\n esac\n}\nwait_http() {\n http_release=$1\n http_port=$2\n shift 2\n https_domain=''\n if [ -f \"$http_release/https\" ]; then\n read -r https_domain https_port https_type < \"$http_release/https\"\n https_certificates=\"$http_release/tls\"\n if [ \"$https_type\" = letsencrypt ]; then https_certificates=\"$root/https/certificates/$https_domain\"; fi\n fi\n for http_path in \"$@\"; do\n http_ready=false\n http_attempt=0\n while [ \"$http_attempt\" -lt 40 ]; do\n if [ -n \"$https_domain\" ]; then\n if curl --noproxy '*' -fsS --max-time 5 --cacert \"$https_certificates/fullchain.pem\" --resolve \"$https_domain:$https_port:127.0.0.1\" \"https://$https_domain:$https_port$http_path\" >/dev/null 2>&1; then http_ready=true; break; fi\n elif curl --noproxy '*' -fsS --max-time 5 \"http://127.0.0.1:$http_port$http_path\" >/dev/null 2>&1; then http_ready=true; break; fi\n http_attempt=$((http_attempt + 1))\n sleep 3\n done\n test \"$http_ready\" = true || { printf 'HTTP check failed: %s. Inspect compose logs for selected services.\\n' \"$http_path\" >&2; return 1; }\n done\n}\nverify_recovery() {\n # 回滚使用旧发布的端口与探测路径,不能用失败新包的地址证明旧服务健康。\n recovery_release=\"$root/releases/$previous\"\n recovery_port=$(awk -F: 'NR == 1 { print $1 }' \"$recovery_release/layout\") || return 1\n recovery_paths=''\n if [ -f \"$recovery_release/health-paths\" ]; then\n recovery_paths=$(cat \"$recovery_release/health-paths\") || return 1\n else\n # 旧格式发布没有独立健康文件;按已存拓扑恢复最小 HTTP 检查。\n recovery_proxy=$(awk -F: 'NR == 1 { print $3 }' \"$recovery_release/layout\") || return 1\n recovery_primary=$(awk -F: 'NR == 1 { print $4 }' \"$recovery_release/layout\") || return 1\n if [ \"$recovery_proxy\" = true ]; then recovery_paths='/health /_hai/web-health /';\n elif [ \"$recovery_primary\" = web ]; then recovery_paths='/'; else recovery_paths='/health'; fi\n fi\n case \"$recovery_port\" in ''|*[!0-9]*) return 1;; esac\n wait_services $recover_selected || return 1\n start_renewal $recover_selected || return 1\n reload_retained_proxy \"$recovery_release\" || return 1\n wait_http \"$recovery_release\" \"$recovery_port\" $recovery_paths\n}\nfinish() {\n code=$?\n trap - EXIT HUP INT TERM\n if [ \"$code\" -ne 0 ]; then\n printf '[FAIL] %s (exit %s)\\n' \"$stage\" \"$code\" >&2\n if [ \"$changed\" = true ]; then\n diagnostics=\"$root/diagnostics-$id.log\"\n : > \"$diagnostics\"\n for service in $selected; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -aq || true)\n for container in $containers; do\n \"$runtime\" inspect --format '{{.Name}} {{.State.Status}} exit={{.State.ExitCode}}' \"$container\" >> \"$diagnostics\" 2>&1 || true\n \"$runtime\" logs --tail 80 \"$container\" >> \"$diagnostics\" 2>&1 || true\n done\n done\n printf 'Startup diagnostics saved to %s (private server file).\\n' \"$diagnostics\" >&2\n fi\n # 只有本次实际开始导入镜像才能恢复标签;重复 ID/校验失败不能重放历史恢复记录。\n if [ \"$images_changed\" = true ] && [ -f \"$release/rollback-images\" ]; then\n while IFS=' ' read -r image reference; do\n test -n \"$reference\" || continue\n if ! \"$runtime\" tag \"$image\" \"$reference\"; then\n recovery_status=failed\n printf '[FAIL] Cannot restore image %s\\n' \"$reference\" >&2\n fi\n done < \"$release/rollback-images\"\n fi\n if [ \"$changed\" = true ] && [ -n \"$previous\" ]; then\n printf '[RECOVER] Restoring previous selected services\\n' >&2\n recover_selected=$selected\n if [ \"$partial\" = false ]; then recover_selected=$(cat \"$root/releases/$previous/services\"); fi\n restore=\"$previous\"\n if sh \"$release/resolve-backend-state.sh\" \"$root\" \"$release\" \"$runtime\" \"$previous\" recover && remove_selected $recover_selected && start_services $recover_selected && verify_recovery && [ \"$recovery_status\" != failed ]; then\n recovery_status=passed\n printf '[RECOVER] Previous release passed recovery health checks\\n' >&2\n else\n recovery_status=failed\n printf '[FAIL] Recovery failed. Use the previous release and inspect container logs.\\n' >&2\n fi\n elif [ \"$changed\" = true ]; then\n if compose stop $selected; then\n recovery_status=stopped\n printf '[RECOVER] Failed first installation stopped; data volumes retained\\n' >&2\n else\n recovery_status=failed\n printf '[FAIL] Could not stop failed first installation; inspect containers.\\n' >&2\n fi\n fi\n fi\n if [ \"$locked\" = true ]; then\n if [ \"$result_owned\" = true ]; then\n elapsed=$(( $(date +%s) - started ))\n outcome=passed\n if [ \"$code\" -ne 0 ]; then outcome=failed; fi\n printf '{\"stage\":\"%s\",\"status\":\"%s\",\"durationSeconds\":%s}\\n' \"$stage\" \"$outcome\" \"$(( $(date +%s) - step_started ))\" >> \"$root/steps-$id.jsonl\"\n # 先完整写入再同目录原子发布,SSH 重连核对不能读取到半份终态结果。\n printf '{\"deploymentId\":\"%s\",\"stage\":\"%s\",\"exitCode\":%s,\"durationSeconds\":%s,\"recoveryStatus\":\"%s\"}\\n' \"$id\" \"$stage\" \"$code\" \"$elapsed\" \"$recovery_status\" > \"$root/result-$id.json.next\"\n mv \"$root/result-$id.json.next\" \"$root/result-$id.json\"\n fi\n # 前台命令及同步恢复已结束;后台服务可继续运行,但不能使成功终态永久占锁。\n # 中断时仍可能有活跃子命令,必须由全部描述符持有者退出后释放。\n if [ \"$interrupted\" = false ]; then\n flock -u 9\n exec 9>&-\n fi\n fi\n exit \"$code\"\n}\ntrap finish EXIT\ntrap 'interrupted=true; exit 130' HUP INT TERM\nstep preflight 'Checking deployment tools and package'\nfor tool in sha256sum tar awk curl flock; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\nif [ \"$runtime\" = auto ]; then\n if command -v podman >/dev/null 2>&1 && podman version >/dev/null 2>&1; then runtime=podman; else runtime=docker; fi\nfi\ncase \"$runtime\" in docker|podman) ;; *) printf 'Runtime must be docker or podman\\n' >&2; exit 1;; esac\n\"$runtime\" version >/dev/null\n\"$runtime\" compose version >/dev/null\n\"$runtime\" compose up --help | grep -q never || { printf 'Compose is too old. Install Docker Compose v2 or podman-compose 1.6.0 or newer (supports --pull never).\\n' >&2; exit 1; }\n# 内核锁绑定同一文件描述符;绝不删除/替换锁文件,避免新 inode 绕过活跃部署。\n# 子命令继承 FD 9:即使父 shell 被强杀,仍执行的命令继续持锁;全部退出或重启后自动释放。\nexec 9>\"$root/.deploy.lock\"\nif flock -n 9; then\n :\nelse\n lock_code=$?\n if [ \"$lock_code\" -eq 1 ]; then\n printf 'Another deployment is running. Wait for its commands to finish; do not remove %s/.deploy.lock.\\n' \"$root\" >&2\n else\n printf 'Cannot acquire deployment lock (exit %s). Check filesystem flock support and permissions.\\n' \"$lock_code\" >&2\n fi\n exit \"$lock_code\"\nfi\nlocked=true\n# 已使用或中断留下的 ID 不能重新认领,尤其不能覆盖原终态和步骤证据。\nif [ -e \"$release\" ] || [ -L \"$release\" ] || [ -e \"$root/result-$id.json\" ] || [ -L \"$root/result-$id.json\" ] || [ -e \"$root/steps-$id.jsonl\" ] || [ -L \"$root/steps-$id.jsonl\" ] || [ -e \"$root/result-$id.json.next\" ] || [ -L \"$root/result-$id.json.next\" ]; then\n printf 'This deployment ID was already used. Create a new deployment bundle.\\n' >&2\n exit 1\nfi\nresult_owned=true\ncd \"$source_dir\"\nsha256sum -c SHA256SUMS\nif [ -f \"$root/current\" ]; then\n previous=$(cat \"$root/current\")\n case \"$previous\" in ''|*[!a-zA-Z0-9._-]*) printf 'Invalid deployment state\\n' >&2; exit 1;; esac\n test -f \"$root/releases/$previous/compose-files\"\nfi\n# 独立持久账本覆盖暂时移除的服务和首次失败留下的卷,预检不写状态。\nsh \"$source_dir/resolve-backend-state.sh\" \"$root\" \"$source_dir\" \"$runtime\" \"$previous\" check\nif [ \"$partial\" = true ]; then\n test -n \"$previous\" || { printf 'Partial deployment requires a successful full installation. Deploy a complete bundle first.\\n' >&2; exit 1; }\n # 目录属于完整Web拓扑;旧版本缺省为根目录,服务增量不能意外丢失或改变既有目录。\n read_deployment_metadata() {\n if [ -e \"$1\" ] || [ -L \"$1\" ]; then\n test -f \"$1\" && test ! -L \"$1\" || { printf 'Deployment path/config metadata must be a regular file.\\n' >&2; return 1; }\n cat \"$1\"\n fi\n }\n current_web_base=$(read_deployment_metadata \"$source_dir/web-base-path\")\n previous_web_base=$(read_deployment_metadata \"$root/releases/$previous/web-base-path\")\n test \"$current_web_base\" = \"$previous_web_base\" || { printf 'Web base path changed. Match the installed prefix for partial updates, or create a full deployment.\\n' >&2; exit 1; }\n current_storage_routing=$(read_deployment_metadata \"$source_dir/storage-routing\")\n previous_storage_routing=$(read_deployment_metadata \"$root/releases/$previous/storage-routing\")\n test \"$current_storage_routing\" = \"$previous_storage_routing\" || { printf 'Managed storage configuration changed. Create a full deployment to switch its public endpoint, bucket, or access policy consistently.\\n' >&2; exit 1; }\n if ! cmp -s layout \"$root/releases/$previous/layout\"; then\n # 容量调整允许复用已部署 Web 镜像;端口、路由及其余代理策略仍要求全量部署。\n test \"$(awk -F: '{print $1 \":\" $2 \":\" $3 \":\" $4 \":\" $6}' layout)\" = \"$(awk -F: '{print $1 \":\" $2 \":\" $3 \":\" $4 \":\" $6}' \"$root/releases/$previous/layout\")\" || { printf 'Ports, HTTPS or application layout changed. Create a full deployment bundle.\\n' >&2; exit 1; }\n test -f web.conf && test -f proxy-entry.json || { printf 'Proxy configuration missing. Create a full deployment bundle.\\n' >&2; exit 1; }\n previous_proxy=\n while IFS= read -r compose_file; do\n candidate_proxy=\"$(dirname -- \"$compose_file\")/web.conf\"\n if [ -f \"$candidate_proxy\" ]; then previous_proxy=$candidate_proxy; fi\n done < \"$root/releases/$previous/compose-files\"\n test -n \"$previous_proxy\" || { printf 'Proxy baseline missing. Create a full deployment bundle.\\n' >&2; exit 1; }\n previous_shape=$(sed 's/client_max_body_size [0-9][0-9]*;/client_max_body_size TRANSPORT;/' \"$previous_proxy\" | sha256sum)\n current_shape=$(sed 's/client_max_body_size [0-9][0-9]*;/client_max_body_size TRANSPORT;/' web.conf | sha256sum)\n test \"$previous_shape\" = \"$current_shape\" || { printf 'API routes or proxy policy changed. Create a full deployment bundle.\\n' >&2; exit 1; }\n case \" $selected \" in *' @@PRIMARY@@ '*) ;; *) printf 'Transport capacity changes require the primary application service. Include it in the partial deployment.\\n' >&2; exit 1;; esac\n current_proxy=$(read_proxy_service \"$source_dir\") || exit 1\n test -n \"$current_proxy\" || { printf 'Proxy service metadata missing. Create a full deployment bundle.\\n' >&2; exit 1; }\n case \" $selected \" in *\" $current_proxy \"*) ;; *) selected=\"$selected $current_proxy\"; proxy_update=true;; esac\n fi\nfi\nmkdir -p \"$release\"\n# 镜像直接从本次解包目录导入;发布记录只保存运行配置与恢复证据。\nfor entry in \"$source_dir\"/* \"$source_dir\"/.[!.]*; do\n test -e \"$entry\" || continue\n test \"$entry\" != \"$source_dir/images\" || continue\n cp -R \"$entry\" \"$release/\"\ndone\n# Nginx 以非 root 用户运行;只开放不含凭据的代理配置读取权限。\nif [ -f \"$release/web.conf\" ]; then chmod 644 \"$release/web.conf\"; fi\nfor https_script in https-start.sh renew-https.sh; do\n if [ -f \"$release/$https_script\" ]; then chmod 444 \"$release/$https_script\"; fi\ndone\n# 策略不是凭据,发布目录保持700;只读挂载允许镜像中的非root应用读取。\nif [ -f \"$release/request-access.yml\" ]; then chmod 444 \"$release/request-access.yml\"; fi\n: > \"$release/compose-files\"\nif [ \"$partial\" = true ]; then\n cp \"$root/releases/$previous/compose-files\" \"$release/compose-files\"\n # 旧版本的生成文件混有镜像原生变量;每项单行,只继承框架连接配置。\n awk '/^HAI_[A-Z0-9_]+=/ { print }' \"$root/releases/$previous/middleware.env\" > \"$release/middleware.env\"\n for service in $selected; do\n grep -qx \"$service\" \"$root/releases/$previous/services\" || { printf 'Service %s has no installed baseline. Use a full deployment.\\n' \"$service\" >&2; exit 1; }\n done\nfi\nstep credentials 'Resolving server-managed middleware credentials'\nsh \"$release/resolve-managed-secrets.sh\" \"$root\" \"$release\" \"$runtime\"\nif [ -f \"$release/runtime-env.mjs\" ]; then\n # 上级目录保护宿主秘密;只读文件挂载允许非 root 应用读取,宿主所有者仍可修改配置。\n chmod 700 \"$root\" \"$release\"\n chmod 644 \"$release/.env.runtime\" \"$release/middleware.env\"\n chmod 444 \"$release/runtime-env.mjs\"\nfi\n# 在任何可能启动服务(包括增量恢复旧拓扑)之前定稿,失败回滚不删除卷的引擎身份。\nsh \"$release/resolve-backend-state.sh\" \"$root\" \"$release\" \"$runtime\" \"$previous\" commit\nprintf '%s\\n' \"$release/compose-entry.json\" >> \"$release/compose-files\"\nif [ \"$proxy_update\" = true ]; then\n printf '%s\\n' \"$release/proxy-entry.json\" >> \"$release/compose-files\"\nfi\ncompose config >/dev/null\ncompose config --services > \"$release/services\"\n# 增量包依赖已安装的完整基线;先恢复 down/stop 后的服务,使用旧配置和本地镜像,不重建运行中的容器。\nif [ \"$partial\" = true ]; then\n recover=false\n while IFS= read -r service; do\n case \" $selected \" in *\" $service \"*) continue;; esac\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -q)\n if [ -z \"$containers\" ]; then recover=true; fi\n done < \"$release/services\"\n if [ \"$recover\" = true ]; then\n step recover 'Starting stopped services from the installed baseline'\n restore=$previous\n sh \"$release/resolve-backend-state.sh\" \"$root\" \"$release\" \"$runtime\" \"$previous\" recover\n start_services $(cat \"$root/releases/$previous/services\")\n restore=''\n fi\nfi\n: > \"$release/rollback-images\"\nif [ -n \"$previous\" ]; then\n for service in $selected; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -aq)\n for container in $containers; do\n \"$runtime\" inspect --format '{{.Image}} {{.Config.Image}}' \"$container\" >> \"$release/rollback-images\"\n done\n done\nfi\nstep images 'Loading packaged images (no registry access)'\nwhile IFS=' ' read -r archive reference; do\n test -n \"$archive\" || continue\n images_changed=true\n \"$runtime\" load -i \"$source_dir/images/$archive\"\n \"$runtime\" image inspect \"$reference\" >/dev/null\n architecture=$(\"$runtime\" image inspect --format '{{.Architecture}}' \"$reference\")\n host_arch=$(uname -m)\n case \"$host_arch:$architecture\" in x86_64:amd64|aarch64:arm64) ;; *) printf 'Image architecture %s does not match server %s\\n' \"$architecture\" \"$host_arch\" >&2; exit 1;; esac\ndone < \"$release/image-list\"\nif [ -f \"$release/prepare-https.sh\" ]; then\n sh \"$release/prepare-https.sh\" \"$root\" \"$release\" \"$runtime\" prepare \"$partial\"\nfi\nstep dependencies 'Checking dependencies of selected services'\nif [ \"$partial\" = true ]; then cat \"$release/services\" >> \"$release/dependencies\"; fi\nwhile IFS= read -r dependency; do\n test -n \"$dependency\" || continue\n case \" $selected \" in *\" $dependency \"*) continue;; esac\n wait_services \"$dependency\"\ndone < \"$release/dependencies\"\nstep start 'Updating selected services'\nchanged=true\nremove_selected $selected\nstart_services $selected\nif [ -f \"$release/prepare-https.sh\" ] && [ \"$partial\" = false ]; then\n step https 'Issuing or installing HTTPS certificate'\n tls_proxy=$(read_proxy_service \"$release\")\n wait_services \"$tls_proxy\"\n sh \"$release/prepare-https.sh\" \"$root\" \"$release\" \"$runtime\" issue \"$partial\"\n compose exec -T \"$tls_proxy\" nginx -t\n compose exec -T \"$tls_proxy\" nginx -s reload\nfi\nstart_renewal $selected\nreload_retained_proxy \"$release\"\nstep health 'Checking HTTP access'\nwait_http \"$release\" @@PORT@@ @@HEALTH@@\nstep complete 'Deployment passed all checks'\nprintf '%s\\n' \"$id\" > \"$root/current.next\"\nmv \"$root/current.next\" \"$root/current\"\ncase \" $selected \" in *' @@PRIMARY@@ '*)\n if grep -q '^HAI_ADMIN_DEFAULT_PASSWORD=' \"$release/.env.runtime\"; then\n printf '[INFO] Initial administrator password source: %s/.env.runtime (HAI_ADMIN_DEFAULT_PASSWORD). Existing users keep their passwords.\\n' \"$release\"\n fi\n ;;\nesac\nprintf '[PASS] %s\\n' \"$id\"\n`.replace(/@@([A-Z]+)@@/g, (_match, name: string) => values[name]!)\n}\n\n/**\n * 生成无 Node/pnpm 依赖的上传脚本;换电脑时可覆盖 SSH 私钥路径。\n * Windows PowerShell 5 会丢弃原生参数内部引号,须直接按 Win32 规则构造命令行。\n * 两个入口执行时读取旁边的 deploy-target.json;apply 阶段 SSH 失败仍须核对远端状态。\n * @returns Linux shell、Windows PowerShell 上传入口及 POSIX awk 配置读取器文本。\n * @example 模块内部上下文\n * ```ts\n * const scripts = createUploadScripts()\n * const files = { 'deploy.sh': scripts.sh, 'deploy.ps1': scripts.ps1, 'read-target.awk': scripts.reader }\n * // 将三个文件与 deploy-target.json 放在操作目录;生成文本不代表已部署。\n * ```\n */\nexport function createUploadScripts(): { sh: string, ps1: string, reader: string } {\n const sh = String.raw`#!/bin/sh\n# 操作机上传入口:整个交付目录可直接复制;tar、deploy-target.json 与本脚本须放在同一目录。\n# 先修改 deploy-target.json 的服务器、用户、密钥路径;需要 sh、awk 及 OpenSSH 的 ssh/scp。\n# 密码缺失时从终端隐藏输入,需要 stty;输入仅用于本次部署。\n# 执行:sh deploy.sh [主机 [端口 [用户]]];可用 HAI_DEPLOY_IDENTITY_FILE 覆盖当前电脑的私钥。\n# tar 内 manifest.json 的 partial/selectedServices 说明本次模式;服务器会核验增量基线,上传后自动部署并检查 HTTP。\nset -eu\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\ncd \"$source_dir\"\ncommand -v awk >/dev/null || { printf 'Install POSIX awk to read deploy-target.json.\\n' >&2; exit 1; }\nread_target() {\n LC_ALL=C awk -v field=\"$1\" -v expected=\"$2\" -v fallback=\"$3\" -f \"$source_dir/read-target.awk\" \"$source_dir/deploy-target.json\"\n}\nhost=$(read_target host string SERVER_HOST)\nuser=$(read_target username string deploy)\nport=$(read_target port number 22)\nremote=$(read_target directory string '')\nbundle=$(read_target bundle string '')\nidentity=$(read_target identityFile string '')\nknown_hosts=$(read_target knownHostsFile string '')\nstrict=$(read_target strictHostKeyChecking boolean true)\ntimeout=$(read_target connectTimeoutSeconds number 10)\nauth=$(read_target auth string key)\npassword_env=$(read_target passwordEnv string HAI_DEPLOY_PROVIDER_SSH_PASSWORD)\ntest -z \"$(read_target password string '')\" || { printf 'Password values are forbidden in deploy-target.json. Use passwordEnv.\\n' >&2; exit 1; }\nif [ \"$#\" -ge 1 ]; then host=$1; fi\nif [ \"$#\" -ge 2 ]; then port=$2; fi\nif [ \"$#\" -ge 3 ]; then user=$3; fi\nif value=$(printenv HAI_DEPLOY_IDENTITY_FILE) && [ -n \"$value\" ]; then identity=$value; fi\nif value=$(printenv HAI_DEPLOY_KNOWN_HOSTS_FILE) && [ -n \"$value\" ]; then known_hosts=$value; fi\ninvalid_target() { printf 'Invalid deployment target. Edit deploy-target.json before running this script.\\n' >&2; exit 1; }\ntest \"$host\" != SERVER_HOST || { printf 'Specify the server: sh deploy.sh SERVER [PORT] [USER].\\n' >&2; exit 1; }\ncase \"$host\" in ''|*[!a-zA-Z0-9.:-]*|[!a-zA-Z0-9]*) invalid_target;; esac\ncase \"$user\" in ''|*[!a-zA-Z0-9_-]*|[!a-zA-Z_]*) invalid_target;; esac\ncase \"$port\" in ''|*[!0-9]*|???????????*) invalid_target;; esac\ntest \"$port\" -ge 1 && test \"$port\" -le 65535 || invalid_target\ncase \"$timeout\" in ''|*[!0-9]*|???????????*) invalid_target;; esac\ntest \"$timeout\" -ge 1 && test \"$timeout\" -le 2147483647 || invalid_target\ncase \"$remote\" in /*) ;; *) invalid_target;; esac\ncase \"$remote\" in *[!a-zA-Z0-9/_.\\ -]*|*/../*|*/..|/..) invalid_target;; esac\ncase \"$bundle\" in *.tar|*.tar.gz) ;; *) invalid_target;; esac\ncase \"$bundle\" in ''|*[!a-zA-Z0-9_.+-]*) invalid_target;; esac\ncase \"$strict\" in true) strict=accept-new;; false) strict=no;; *) invalid_target;; esac\ntest -f \"./$bundle\" || { printf 'Bundle missing: %s\\n' \"$bundle\" >&2; exit 1; }\nfor tool in ssh scp; do command -v \"$tool\" >/dev/null || { printf 'Install OpenSSH (%s).\\n' \"$tool\" >&2; exit 1; }; done\ntemporary=''\ntemporary_root=''\nupload=''\nmonitor=''\ntty_state=''\ncleanup() {\n # 中断隐藏输入时也恢复调用者的终端回显。\n if [ -n \"$tty_state\" ]; then\n (stty \"$tty_state\" </dev/tty; printf '\\n' >/dev/tty) 2>/dev/null || :\n fi\n if [ -n \"$monitor\" ]; then kill \"$monitor\" 2>/dev/null || :; wait \"$monitor\" 2>/dev/null || :; fi\n if [ -n \"$upload\" ]; then kill \"$upload\" 2>/dev/null || :; wait \"$upload\" 2>/dev/null || :; fi\n if [ -n \"$temporary\" ]; then\n case \"$temporary\" in \"$temporary_root\"/hai-ssh-askpass.*) test ! -L \"$temporary\" && rm -rf -- \"$temporary\";; *) return 1;; esac\n fi\n}\ntrap cleanup EXIT\ntrap 'exit 130' HUP INT TERM\ncase \"$auth\" in key|password) ;; *) invalid_target;; esac\ncase \"$password_env\" in HAI_DEPLOY_[A-Z0-9_]*) ;; *) invalid_target;; esac\ncase \"$password_env\" in *[!A-Z0-9_]*) invalid_target;; esac\nset -- -o \"StrictHostKeyChecking=$strict\" -o \"ConnectTimeout=$timeout\"\nif [ \"$auth\" = password ]; then\n for tool in mktemp mkfifo od; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\n # 后缀哨兵保留末尾换行,以便拒绝 readpass 无法安全传递的 CR/LF。\n password=''\n if password=$(printenv \"$password_env\" && printf '.'); then\n password=@@PASSWORD_TRIM@@\n password=@@PASSWORD_NEWLINE@@\n fi\n if [ -z \"$password\" ]; then\n if ! command -v stty >/dev/null || ! ( : </dev/tty >/dev/tty ) 2>/dev/null; then\n printf '%s: %s\\n' \"$password_env\" @@PASSWORD_UNAVAILABLE@@ >&2\n exit 1\n fi\n tty_state=$(stty -g </dev/tty)\n stty -echo </dev/tty\n printf '%s (%s): ' @@PASSWORD_PROMPT@@ \"$password_env\" >/dev/tty\n if IFS= read -r password </dev/tty; then input_code=0; else input_code=$?; fi\n stty \"$tty_state\" </dev/tty\n tty_state=''\n printf '\\n' >/dev/tty\n if [ \"$input_code\" -ne 0 ]; then printf '%s\\n' @@PASSWORD_CANCELLED@@ >&2; exit 1; fi\n fi\n export HAI_DEPLOY_ASKPASS_PASSWORD=\"$password\"\n if ! LC_ALL=C awk 'BEGIN {p=ENVIRON[\"HAI_DEPLOY_ASKPASS_PASSWORD\"]; exit (length(p) == 0 || length(p) > 1023 || p ~ /[\\r\\n]/) ? 1 : 0}'; then printf '%s: %s\\n' \"$password_env\" @@PASSWORD_INVALID@@ >&2; exit 1; fi\n umask 077\n temporary_root=$(CDPATH= cd -- \"@@TEMP_ROOT@@\" && pwd -P)\n temporary=$(mktemp -d \"$temporary_root/hai-ssh-askpass.XXXXXXXX\")\n cat > \"$temporary/askpass.sh\" <<'HAI_ASKPASS'\n#!/bin/sh\ntest \"@@ASKPASS_PROMPT@@\" != confirm || exit 1\ntest -n \"$HAI_DEPLOY_ASKPASS_PASSWORD\" || exit 1\nprintf '%s\\n' \"$HAI_DEPLOY_ASKPASS_PASSWORD\"\nHAI_ASKPASS\n chmod 700 \"$temporary/askpass.sh\"\n export SSH_ASKPASS=\"$temporary/askpass.sh\" SSH_ASKPASS_REQUIRE=force SSH_ASKPASS_PROMPT='' DISPLAY=hai-deploy:0\n set -- \"$@\" -o BatchMode=no -o PreferredAuthentications=password -o PasswordAuthentication=yes -o PubkeyAuthentication=no -o NumberOfPasswordPrompts=1\nelse\n set -- \"$@\" -o BatchMode=yes\n if [ -n \"$identity\" ]; then set -- \"$@\" -i \"$identity\" -o IdentitiesOnly=yes; fi\nfi\n# 固定字节流过滤器最多保留一个密码长度,不把值交给 argv、正则或磁盘。\nrun_native() {\n if [ \"$auth\" = key ]; then \"$@\"; return; fi\n # 每次调用独立管道,允许上传与进度查询并行且保持密码脱敏。\n output=$(mktemp \"$temporary/output.XXXXXXXX\") || return 1\n rm -f \"$output\"\n mkfifo \"$output\" || return 1\n (od -An -v -tu1 \"$output\" | LC_ALL=C awk '\n BEGIN {secret=ENVIRON[\"HAI_DEPLOY_ASKPASS_PASSWORD\"]; n=length(secret); pending=\"\"}\n {for(i=1;i<=NF;i++) {pending=pending sprintf(\"%c\",$i); while(length(pending)>=n) {\n if(substr(pending,1,n)==secret) {printf \"***\"; pending=substr(pending,n+1)}\n else {printf \"%s\",substr(pending,1,1); pending=substr(pending,2)}\n }}}\n END {printf \"%s\",pending}') &\n filter=$!\n if \"$@\" > \"$output\" 2>&1; then code=0; else code=$?; fi\n if ! wait \"$filter\"; then printf 'Cannot filter SSH output.\\n' >&2; return 1; fi\n rm -f \"$output\"\n return \"$code\"\n}\nif [ -n \"$known_hosts\" ]; then\n known_hosts=$(printf '%s' \"$known_hosts\" | sed 's/[\\\\\"]/\\\\&/g')\n set -- \"$@\" -o \"UserKnownHostsFile=\\\"$known_hosts\\\"\"\nfi\nprintf '[1/3] Connecting to %s\\n' \"$host\"\nrun_native ssh \"$@\" -p \"$port\" \"$user@$host\" \"mkdir -p '$remote/incoming' && chmod 700 '$remote' '$remote/incoming'\"\nprintf '[2/3] Uploading %s\\n' \"$bundle\"\nscp_host=$host\ncase \"$host\" in *:*) scp_host=\"[$host]\";; esac\ntotal=$(wc -c < \"./$bundle\" | tr -d '[:space:]')\nprintf '[UPLOAD] 0%% (0/%s bytes)\\n' \"$total\"\nrun_native scp \"$@\" -P \"$port\" \"./$bundle\" \"$user@$scp_host:$remote/incoming/$bundle\" &\nupload=$!\n(\n pause=''\n trap 'if [ -n \"$pause\" ]; then kill \"$pause\" 2>/dev/null || :; wait \"$pause\" 2>/dev/null || :; fi; exit 0' HUP INT TERM\n while kill -0 \"$upload\" 2>/dev/null; do\n sleep 2 &\n pause=$!\n wait \"$pause\" || exit 1\n pause=''\n kill -0 \"$upload\" 2>/dev/null || break\n received=$(run_native ssh \"$@\" -p \"$port\" \"$user@$host\" \"wc -c < '$remote/incoming/$bundle'\" 2>/dev/null) || continue\n received=$(printf '%s' \"$received\" | tr -d '[:space:]')\n case \"$received\" in ''|*[!0-9]*) continue;; esac\n LC_ALL=C awk -v done=\"$received\" -v total=\"$total\" 'BEGIN {percent=total>0 ? done*100/total : 0; if(percent>99) percent=99; printf \"[UPLOAD] %.0f%% (%s/%s bytes)\\n\",percent,done,total}'\n done\n) &\nmonitor=$!\nif wait \"$upload\"; then upload_code=0; else upload_code=$?; fi\nupload=''\nkill \"$monitor\" 2>/dev/null || :\nwait \"$monitor\" 2>/dev/null || :\nmonitor=''\nif [ \"$upload_code\" -ne 0 ]; then printf '[FAIL] Upload failed (exit %s). Check SSH output above.\\n' \"$upload_code\" >&2; exit \"$upload_code\"; fi\nprintf '[UPLOAD] 100%% (%s/%s bytes)\\n' \"$total\" \"$total\"\nprintf '[3/3] Applying package and checking HTTP access\\n'\nif run_native ssh \"$@\" -p \"$port\" \"$user@$host\" \"cd '$remote/incoming' && mkdir -p '$bundle.contents' && tar -xf '$bundle' -C '$bundle.contents' && sh '$bundle.contents/apply.sh' '$remote' && { rm -rf -- '$bundle.contents' && rm -f -- '$bundle' || printf '[WARN] Deployment passed; incoming archive cleanup failed\\\\n' >&2; }\"; then\n :\nelse\n code=$?\n if [ \"$code\" -lt 128 ]; then\n printf '[FAIL] Remote deployment failed (exit %s). Inspect %s/result-<deploymentId>.json (ID in README.txt) and startup diagnostics.\\n' \"$code\" \"$remote\" >&2\n else\n printf '[UNKNOWN] Remote execution may continue. Inspect %s/result-<deploymentId>.json (ID in README.txt), current and containers before retrying.\\n' \"$remote\" >&2\n fi\n exit \"$code\"\nfi\n`.replace('@@PASSWORD_TRIM@@', '$' + '{password%.}').replace('@@PASSWORD_NEWLINE@@', '$' + '{password%?}').replace('@@TEMP_ROOT@@', '$' + '{TMPDIR:-/tmp}').replace('@@ASKPASS_PROMPT@@', '$' + '{SSH_ASKPASS_PROMPT:-}')\n const ps1 = String.raw`<#\n操作机上传入口:复制整个交付目录后,先修改同目录 deploy-target.json 的服务器、用户和密钥路径。\n需要 Windows PowerShell 5+/PowerShell 及 OpenSSH 的 ssh/scp;tar 必须与本脚本放在同一目录。\n执行:powershell -File .\\deploy.ps1 [-IdentityFile 当前电脑的私钥路径]。\ntar 内 manifest.json 的 partial/selectedServices 标明全量或增量;服务器会检查基线,上传后自动部署并核验 HTTP。\nSSH 中断时先核对远端结果文件和容器状态,再决定是否重试。\n#>\nparam([string]$IdentityFile = $env:HAI_DEPLOY_IDENTITY_FILE)\n$ErrorActionPreference = 'Stop'\n# Windows PowerShell 5 的重定向错误流默认沿用本机代码页;统一 UTF-8,保留多语言提示。\n[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)\n$OutputEncoding = [Console]::OutputEncoding\n$windowsRuntime = [Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT\n$previousSystemRoot = [Environment]::GetEnvironmentVariable('SystemRoot', 'Process')\ntry {\nif ($windowsRuntime) {\n $windowsDirectory = [Environment]::GetFolderPath('Windows')\n if ([string]::IsNullOrEmpty($windowsDirectory)) { throw 'Cannot locate the Windows system directory.' }\n $env:SystemRoot = $windowsDirectory\n}\nSet-Location -LiteralPath $PSScriptRoot\n$target = Get-Content -LiteralPath (Join-Path $PSScriptRoot 'deploy-target.json') -Raw -Encoding UTF8 | ConvertFrom-Json\nif ($target.host -eq 'SERVER_HOST') { throw 'Set the server host in deploy-target.json.' }\nif ($target.host -isnot [string] -or $target.host -notmatch '^[a-zA-Z0-9][a-zA-Z0-9.:-]*$' -or $target.username -isnot [string] -or $target.username -notmatch '^[a-zA-Z_][a-zA-Z0-9_-]*$' -or $target.directory -isnot [string] -or $target.directory -notmatch '^/[a-zA-Z0-9/_. -]*$' -or $target.directory -match '(^|/)\\.\\.(/|$)' -or $target.bundle -isnot [string] -or $target.bundle -notmatch '^[a-zA-Z0-9_.+-]+\\.tar(\\.gz)?$') { throw 'Invalid deployment target.' }\n$port = if ($null -eq $target.port) { 22 } else { $target.port }\n$timeout = if ($null -eq $target.connectTimeoutSeconds) { 10 } else { $target.connectTimeoutSeconds }\nif ($port -is [string] -or [string]$port -notmatch '^[0-9]+$' -or $port -lt 1 -or $port -gt 65535 -or $timeout -is [string] -or [string]$timeout -notmatch '^[0-9]+$' -or $timeout -lt 1 -or $timeout -gt 2147483647) { throw 'Invalid deployment port or timeout.' }\nif ($null -ne $target.strictHostKeyChecking -and $target.strictHostKeyChecking -isnot [bool]) { throw 'Invalid host key policy.' }\nif (($null -ne $target.identityFile -and $target.identityFile -isnot [string]) -or ($null -ne $target.knownHostsFile -and $target.knownHostsFile -isnot [string])) { throw 'Invalid SSH file path.' }\n$strict = if ($target.strictHostKeyChecking -eq $false) { 'no' } else { 'accept-new' }\n$auth = if ($null -eq $target.auth) { 'key' } else { $target.auth }\n$passwordEnv = if ($null -eq $target.passwordEnv) { 'HAI_DEPLOY_PROVIDER_SSH_PASSWORD' } else { $target.passwordEnv }\nif ($auth -isnot [string] -or $auth -notin @('key', 'password') -or $passwordEnv -isnot [string] -or $passwordEnv -cnotmatch '^HAI_DEPLOY_[A-Z0-9_]+$' -or $null -ne $target.password) { throw 'Invalid SSH authentication configuration. Store only passwordEnv in the target; passwords are read locally or prompted.' }\n$options = @('-o', \"StrictHostKeyChecking=$strict\", '-o', \"ConnectTimeout=$timeout\")\nif (-not $IdentityFile) { $IdentityFile = $target.identityFile }\nif ($auth -eq 'password') {\n $options += @('-o', 'BatchMode=no', '-o', 'PreferredAuthentications=password', '-o', 'PasswordAuthentication=yes', '-o', 'PubkeyAuthentication=no', '-o', 'NumberOfPasswordPrompts=1')\n} else {\n $options += @('-o', 'BatchMode=yes')\n if ($IdentityFile) { $options += @('-i', $IdentityFile, '-o', 'IdentitiesOnly=yes') }\n}\n$knownHosts = if ($env:HAI_DEPLOY_KNOWN_HOSTS_FILE) { $env:HAI_DEPLOY_KNOWN_HOSTS_FILE } else { $target.knownHostsFile }\nif ($knownHosts) {\n $knownHosts = $knownHosts.Replace('\\', '\\\\').Replace('\"', '\\\"')\n $options += @('-o', ('UserKnownHostsFile=\"' + $knownHosts + '\"'))\n}\n$destination = \"$($target.username)@$($target.host)\"\n$scpDestination = if ($target.host.Contains(':')) { \"$($target.username)@[$($target.host)]\" } else { $destination }\n$remote = $target.directory\n$bundle = $target.bundle\nif (-not (Test-Path -LiteralPath \"./$bundle\" -PathType Leaf)) { throw \"Bundle missing: $bundle\" }\nfunction ConvertTo-NativeArgument([string]$Value) {\n if ($Value.Length -gt 0 -and $Value -notmatch '[\\s\"]') { return $Value }\n $escaped = [regex]::Replace($Value, '(\\\\*)\"', '$1$1\\\"')\n $escaped = [regex]::Replace($escaped, '(\\\\+)$', '$1$1')\n return '\"' + $escaped + '\"'\n}\nfunction Invoke-Step([string]$Name, [string]$Command, [string[]]$Arguments) {\n Write-Host \"[$Name]\"\n $nativeCommand = Get-Command $Command -ErrorAction Stop\n if ($auth -eq 'password' -and $nativeCommand.CommandType -eq 'Application') {\n $Arguments = @('--run', $nativeCommand.Source) + $Arguments\n $nativeCommand = Get-Command $env:SSH_ASKPASS -ErrorAction Stop\n }\n if ($nativeCommand.CommandType -eq 'Application') {\n $start = New-Object System.Diagnostics.ProcessStartInfo\n $start.FileName = $nativeCommand.Source\n $start.WorkingDirectory = (Get-Location).ProviderPath\n $start.UseShellExecute = $false\n $start.CreateNoWindow = $true\n $start.RedirectStandardOutput = $true\n $start.RedirectStandardError = $true\n $start.StandardOutputEncoding = New-Object System.Text.UTF8Encoding($false)\n $start.StandardErrorEncoding = New-Object System.Text.UTF8Encoding($false)\n $start.Arguments = ($Arguments | ForEach-Object { ConvertTo-NativeArgument $_ }) -join ' '\n $child = [System.Diagnostics.Process]::Start($start)\n # 持续转发 SSH/部署诊断;密码模式的输出已由独立 helper 脱敏。\n $streams = @(\n @{ Reader = $child.StandardOutput; Pending = $child.StandardOutput.ReadLineAsync(); Writer = [Console]::Out },\n @{ Reader = $child.StandardError; Pending = $child.StandardError.ReadLineAsync(); Writer = [Console]::Error }\n )\n $clock = [Diagnostics.Stopwatch]::StartNew()\n $nextProgress = 2000\n try {\n while (-not $child.HasExited -or $null -ne $streams[0].Pending -or $null -ne $streams[1].Pending) {\n foreach ($stream in $streams) {\n while ($null -ne $stream.Pending -and $stream.Pending.IsCompleted) {\n $line = $stream.Pending.GetAwaiter().GetResult()\n if ($null -eq $line) { $stream.Pending = $null }\n else { $stream.Writer.WriteLine($line); $stream.Pending = $stream.Reader.ReadLineAsync() }\n }\n }\n if ($Command -eq 'scp' -and -not $child.HasExited -and $clock.ElapsedMilliseconds -ge $nextProgress) {\n $nextProgress = $clock.ElapsedMilliseconds + 2000\n $query = $null\n try {\n $probe = New-Object System.Diagnostics.ProcessStartInfo\n $probe.FileName = (Get-Command ssh -ErrorAction Stop).Source\n $probeArgs = $options + @('-p', [string]$port, $destination, \"wc -c < '$remote/incoming/$bundle'\")\n if ($auth -eq 'password') { $probeArgs = @('--run', $probe.FileName) + $probeArgs; $probe.FileName = $env:SSH_ASKPASS }\n $probe.UseShellExecute = $false; $probe.CreateNoWindow = $true\n $probe.RedirectStandardOutput = $true; $probe.RedirectStandardError = $true\n $probe.Arguments = ($probeArgs | ForEach-Object { ConvertTo-NativeArgument $_ }) -join ' '\n $query = [System.Diagnostics.Process]::Start($probe)\n try {\n $stdout = $query.StandardOutput.ReadToEndAsync()\n $stderr = $query.StandardError.ReadToEndAsync()\n if (-not $query.WaitForExit(5000)) { $query.Kill(); $query.WaitForExit() }\n $received = $stdout.Result.Trim()\n if ($query.ExitCode -eq 0 -and $received -match '^[0-9]+$') {\n $percent = if ($uploadBytes -gt 0) { [Math]::Min(99, [Math]::Floor([double]$received * 100 / $uploadBytes)) } else { 0 }\n Write-Host \"[UPLOAD] $percent% ($received/$uploadBytes bytes)\"\n Write-Progress -Activity \"Uploading $bundle\" -Status \"$received/$uploadBytes bytes\" -PercentComplete $percent\n }\n } finally { if ($null -ne $query) { $query.Dispose() } }\n } catch { [Console]::Error.WriteLine('[UPLOAD] Progress query unavailable; transfer continues.') }\n }\n Start-Sleep -Milliseconds 50\n }\n $code = $child.ExitCode\n } finally { $child.Dispose(); if ($Command -eq 'scp') { Write-Progress -Activity \"Uploading $bundle\" -Completed } }\n } else {\n $invokeCommand = if ($nativeCommand.CommandType -eq 'Application') { $nativeCommand.Source } else { $Command }\n & $invokeCommand @Arguments\n $code = $LASTEXITCODE\n }\n $global:LASTEXITCODE = $code\n if ($code -ne 0) { throw \"$Name failed (exit $code).\" }\n}\n$applying = $false\n$temporary = $null\n$temporaryRoot = [System.IO.Path]::GetFullPath([System.IO.Path]::GetTempPath()).TrimEnd([System.IO.Path]::DirectorySeparatorChar)\n$savedEnvironment = @{}\ntry {\n foreach ($tool in @('ssh', 'scp')) { Get-Command $tool -ErrorAction Stop | Out-Null }\n if ($auth -eq 'password') {\n $password = [Environment]::GetEnvironmentVariable($passwordEnv, 'Process')\n if ($null -eq $password -and $windowsRuntime) { $password = [Environment]::GetEnvironmentVariable($passwordEnv, 'User') }\n if ([string]::IsNullOrEmpty($password)) {\n if ($Host.Name -eq 'ConsoleHost' -and [Console]::IsInputRedirected) { throw ($passwordEnv + ': ' + @@PASSWORD_UNAVAILABLE@@) }\n $secure = $null\n $pointer = [IntPtr]::Zero\n try {\n $secure = Read-Host -Prompt (@@PASSWORD_PROMPT@@ + ' (' + $passwordEnv + ')') -AsSecureString\n $pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure)\n $password = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer)\n } catch { throw ($passwordEnv + ': ' + @@PASSWORD_UNAVAILABLE@@) }\n finally {\n if ($pointer -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer) }\n if ($null -ne $secure) { $secure.Dispose() }\n }\n }\n if ([string]::IsNullOrEmpty($password) -or $password.IndexOfAny([char[]]@([char]0, [char]10, [char]13)) -ge 0 -or [Text.Encoding]::UTF8.GetByteCount($password) -gt 1023) { throw ($passwordEnv + ': ' + @@PASSWORD_INVALID@@) }\n foreach ($name in @('SSH_ASKPASS', 'SSH_ASKPASS_REQUIRE', 'SSH_ASKPASS_PROMPT', 'DISPLAY', 'HAI_DEPLOY_ASKPASS_PASSWORD', 'HAI_DEPLOY_ASKPASS_SOURCE', 'HAI_DEPLOY_ASKPASS_OUTPUT')) { $savedEnvironment[$name] = [Environment]::GetEnvironmentVariable($name, 'Process') }\n $temporary = Join-Path $temporaryRoot ('hai-ssh-askpass-' + [Guid]::NewGuid().ToString('N'))\n [System.IO.Directory]::CreateDirectory($temporary) | Out-Null\n $source = Join-Path $temporary 'askpass.cs'\n $helper = Join-Path $temporary 'askpass.exe'\n [System.IO.File]::WriteAllText($source, @'\n@@WINDOWS_ASKPASS@@\n'@, (New-Object System.Text.UTF8Encoding($false)))\n $env:HAI_DEPLOY_ASKPASS_SOURCE = $source\n $env:HAI_DEPLOY_ASKPASS_OUTPUT = $helper\n # 编译进程不继承专用密码;固定源码及命令均不包含凭据。\n $env:HAI_DEPLOY_ASKPASS_PASSWORD = ''\n if (-not $windowsRuntime) { throw 'Use sh deploy.sh for password authentication on POSIX systems.' }\n $compiler = Join-Path $windowsDirectory 'System32/WindowsPowerShell/v1.0/powershell.exe'\n $compileScript = '$ErrorActionPreference=\"Stop\"; Add-Type -Language CSharp -TypeDefinition ([System.IO.File]::ReadAllText($env:HAI_DEPLOY_ASKPASS_SOURCE, [System.Text.Encoding]::UTF8)) -OutputType ConsoleApplication -OutputAssembly $env:HAI_DEPLOY_ASKPASS_OUTPUT'\n & $compiler -NoProfile -NonInteractive -EncodedCommand ([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($compileScript))) 2>&1 | Out-Null\n if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $helper -PathType Leaf)) { throw 'Cannot prepare the SSH password helper.' }\n $env:SSH_ASKPASS = $helper\n $env:SSH_ASKPASS_REQUIRE = 'force'\n $env:SSH_ASKPASS_PROMPT = ''\n $env:DISPLAY = 'hai-deploy:0'\n $env:HAI_DEPLOY_ASKPASS_PASSWORD = $password\n }\n Invoke-Step '1/3 Connect' 'ssh' ($options + @('-p', [string]$port, $destination, \"mkdir -p '$remote/incoming' && chmod 700 '$remote' '$remote/incoming'\"))\n $uploadBytes = (Get-Item -LiteralPath \"./$bundle\").Length\n Write-Host \"[UPLOAD] 0% (0/$uploadBytes bytes)\"\n Invoke-Step '2/3 Upload' 'scp' ($options + @('-P', [string]$port, \"./$bundle\", \"$($scpDestination):$remote/incoming/$bundle\"))\n Write-Host \"[UPLOAD] 100% ($uploadBytes/$uploadBytes bytes)\"\n $applying = $true\n Invoke-Step '3/3 Apply and verify HTTP' 'ssh' ($options + @('-p', [string]$port, $destination, \"cd '$remote/incoming' && mkdir -p '$bundle.contents' && tar -xf '$bundle' -C '$bundle.contents' && sh '$bundle.contents/apply.sh' '$remote' && { rm -rf -- '$bundle.contents' && rm -f -- '$bundle' || printf '[WARN] Deployment passed; incoming archive cleanup failed\\\\n' >&2; }\"))\n} catch {\n if ($applying) {\n if ($LASTEXITCODE -gt 0 -and $LASTEXITCODE -lt 128) { [Console]::Error.WriteLine(\"[FAIL] Remote deployment failed (exit $LASTEXITCODE). Inspect $remote/result-<deploymentId>.json (ID in README.txt) and startup diagnostics.\") }\n else { [Console]::Error.WriteLine(\"[UNKNOWN] Remote execution may continue. Inspect $remote/result-<deploymentId>.json (ID in README.txt), current and containers before retrying.\") }\n }\n throw\n} finally {\n foreach ($name in $savedEnvironment.Keys) { [Environment]::SetEnvironmentVariable($name, $savedEnvironment[$name], 'Process') }\n if ($null -ne $temporary -and (Test-Path -LiteralPath $temporary)) {\n $item = Get-Item -LiteralPath $temporary -Force\n if ([System.IO.Path]::GetDirectoryName([System.IO.Path]::GetFullPath($temporary)) -ne $temporaryRoot -or $item.Name -notlike 'hai-ssh-askpass-*' -or ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) { throw 'Refusing to clean an unexpected SSH helper directory.' }\n Remove-Item -LiteralPath $temporary -Recurse -Force\n }\n}\n} finally {\n if ($windowsRuntime) {\n if ($null -eq $previousSystemRoot) { Remove-Item -LiteralPath Env:SystemRoot -ErrorAction SilentlyContinue }\n else { [Environment]::SetEnvironmentVariable('SystemRoot', $previousSystemRoot, 'Process') }\n }\n}\n`.replace('@@WINDOWS_ASKPASS@@', windowsAskpassSource)\n // Windows PowerShell 5 将无 BOM 的 UTF-8 视为 ANSI;中文注释也可能改变脚本的实际解析结果。\n const messages: Record<string, string> = {\n PROMPT: deployM('deploy_uploadPasswordPrompt'),\n UNAVAILABLE: deployM('deploy_uploadPasswordUnavailable'),\n CANCELLED: deployM('deploy_uploadPasswordCancelled'),\n INVALID: deployM('deploy_uploadPasswordInvalid'),\n }\n const pattern = /@@PASSWORD_(PROMPT|UNAVAILABLE|CANCELLED|INVALID)@@/g\n return {\n sh: sh.replace(pattern, (_match, name: string) => shellArgument(messages[name]!)),\n ps1: `\\uFEFF${ps1.replace(pattern, (_match, name: string) => `'${messages[name]!.replaceAll('\\'', '\\'\\'')}'`)}`,\n reader: createTargetReader(),\n }\n}\n\n/**\n * 生成服务器本地入口,自动解包后调用同一 apply 流程。\n * @param options - 同目录 tar 名称和默认服务器部署目录;都由已校验的部署配置生成。\n * @param options.bundle - 不含目录的 tar 文件名。\n * @param options.directory - 服务器部署目录,执行时可用第一个参数覆盖。\n * @returns 不依赖 Node、pnpm、SSH 或手工解包的 POSIX shell 脚本。\n * @example 模块内部上下文\n * ```ts\n * const script = createLocalInstallScript({ bundle: 'bundle-shop-1.0.0.tar', directory: '/opt/hai/apps/shop-prod' })\n * // 保存为与 tar 同目录的 deploy-local.sh,目标 Linux 直接执行 sh deploy-local.sh。\n * ```\n */\nexport function createLocalInstallScript(options: { bundle: string, directory: string }): string {\n return String.raw`#!/bin/sh\n# 目标服务器本地入口:把整个交付目录复制到 Linux,直接执行 sh deploy-local.sh [服务器部署目录]。\n# 自动解包到本次独立临时目录并调用 apply.sh;不需要手工解包,也不需要 SSH、Node 或 pnpm。\n# 需要 tar、mktemp 和 apply.sh 所列的容器运行环境;全量/增量由 manifest.json 固定,增量要求已有成功基线。\n# 执行日志保留在本交付目录,退出时只清理本次临时解包目录,业务数据由 apply.sh 保留。\nset -eu\numask 077\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\nbundle=@@BUNDLE@@\ndestination=@@DIRECTORY@@\nif [ \"$#\" -gt 0 ]; then destination=$1; fi\nfor tool in tar mktemp date; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\ntest -f \"$source_dir/$bundle\" || { printf 'Bundle missing: %s\\n' \"$bundle\" >&2; exit 1; }\nlog=\"$source_dir/deploy-local-$(date +%Y%m%d-%H%M%S)-$$.log\"\ntemporary=$(mktemp -d /tmp/hai-deploy.XXXXXX)\ncleanup() { rm -rf -- \"$temporary\"; }\ntrap cleanup EXIT\ntrap 'exit 130' HUP INT TERM\nprintf 'Deployment log: %s\\n' \"$log\"\nif (tar -xf \"$source_dir/$bundle\" -C \"$temporary\" && sh \"$temporary/apply.sh\" \"$destination\") > \"$log\" 2>&1; then\n cat \"$log\"\nelse\n code=$?\n cat \"$log\" >&2\n exit \"$code\"\nfi\n`.replace('@@BUNDLE@@', shellArgument(options.bundle)).replace('@@DIRECTORY@@', shellArgument(options.directory))\n}\n","/**\n * @h-ai/deploy — SSH 执行器\n *\n * 基于用户机器已有的 OpenSSH 客户端(ssh / scp)封装远程命令执行与文件上传。\n * 复用 ~/.ssh/config、ssh-agent 与 OpenSSH 证书,避免引入 Node SSH SDK 的密钥兼容问题。\n * 所有调用均以 command + args 数组构造,禁止字符串拼接,防止命令注入。\n * @module deploy-ssh\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { SshConfig } from '../deploy-config.js'\nimport type { CommandOptions, CommandResult } from './deploy-command.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { getDeployCommandState } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { runCommand } from './deploy-command.js'\nimport { prepareSshAskpass } from './deploy-ssh-askpass.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'ssh' })\n\n/**\n * SSH 执行器接口\n * 命令通过远端登录 shell 执行;传入的命令文本必须由受信代码构造。远端副作用与本地 SSH 退出状态分开处理。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const ssh = createSshExecutor(config)\n * const connected = await ssh.ping()\n * if (!connected.success) throw new Error(connected.error.message)\n * ```\n */\nexport interface SshExecutor {\n /** 在远程主机执行命令(通过远程登录 shell 运行) */\n exec: (remoteCommand: string, options?: Pick<CommandOptions, 'timeoutMs' | 'terminationTimeoutMs' | 'secrets' | 'maxCaptureChars' | 'onOutput'>) => Promise<HaiResult<CommandResult>>\n /** 上传本地文件到远程路径 */\n upload: (localPath: string, remotePath: string) => Promise<HaiResult<void>>\n /** 远程连通性预检(执行 true 命令) */\n ping: () => Promise<HaiResult<void>>\n}\n\n/**\n * 显式 key 优先;空密码不会改变省略 auth 时的原 key/agent 默认行为。\n * @example 模块内部上下文\n * ```ts\n * function inspectAuthentication(password: string) {\n * const inferred = usesSshPassword({ password })\n * const explicitKey = usesSshPassword({ auth: 'key', password })\n * return { inferred, explicitKey }\n * }\n * ```\n */\nexport function usesSshPassword(config: Pick<SshConfig, 'auth' | 'password'>): boolean {\n return config.auth === 'password' || (config.auth === undefined && Boolean(config.password))\n}\n\n/** 构造 ssh 公共连接选项;密码从 child env 供给,不进入参数。 */\nfunction buildConnectOptions(config: SshConfig): string[] {\n const password = usesSshPassword(config)\n const args: string[] = ['-o', password ? 'BatchMode=no' : 'BatchMode=yes']\n if (password)\n args.push('-o', 'PreferredAuthentications=password', '-o', 'PasswordAuthentication=yes', '-o', 'PubkeyAuthentication=no', '-o', 'NumberOfPasswordPrompts=1')\n args.push('-o', `ConnectTimeout=${config.connectTimeoutSeconds}`)\n args.push('-o', `StrictHostKeyChecking=${config.strictHostKeyChecking ? 'accept-new' : 'no'}`)\n if (config.knownHostsFile) {\n // OpenSSH 会再次按配置语法解析 -o 的值,路径中的空格须保留内部引号。\n const path = config.knownHostsFile.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')\n args.push('-o', `UserKnownHostsFile=\"${path}\"`)\n }\n if (!password && config.identityFile) {\n args.push('-i', config.identityFile)\n args.push('-o', 'IdentitiesOnly=yes')\n }\n return args\n}\n\n/**\n * 构造 ssh 执行命令的参数数组。\n *\n * remoteCommand 作为单个参数传入,不经过本地 shell 解析,避免本地命令注入。\n * @param config - SSH 连接配置\n * @param remoteCommand - 远程命令字符串\n * @returns 交给本地 ssh 可执行文件的参数数组。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const args = buildSshExecArgs(config, 'true')\n * // 参数供本地无 shell 的 ssh 进程使用;不是可再次拼接进 shell 的字符串。\n * ```\n */\nexport function buildSshExecArgs(config: SshConfig, remoteCommand: string): string[] {\n return [\n ...buildConnectOptions(config),\n '-p',\n String(config.port),\n `${config.username}@${config.host}`,\n remoteCommand,\n ]\n}\n\n/**\n * 构造 scp 上传命令的参数数组。\n * 保留参数数组边界;远端路径只使用内部已校验的部署目录。\n * @param config - SSH 连接配置\n * @param localPath - 本地文件路径\n * @param remotePath - 远程目标路径\n * @returns 交给本地 scp 可执行文件的参数数组。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const args = buildScpUploadArgs(config, '/workspace/shop/.hai/deploy/shop.tar', '/opt/hai/incoming/shop.tar')\n * ```\n */\nexport function buildScpUploadArgs(config: SshConfig, localPath: string, remotePath: string): string[] {\n return [\n ...buildConnectOptions(config),\n '-P',\n String(config.port),\n localPath,\n `${config.username}@${config.host.includes(':') ? `[${config.host}]` : config.host}:${remotePath}`,\n ]\n}\n\n/**\n * 创建 SSH 执行器。\n * 创建执行器不持有长连接;每次 exec/upload/ping 启动独立受管理本地进程并检查 HaiResult。\n * @param config - SSH 连接配置\n * @returns SSH 执行器实例\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const ssh = createSshExecutor(config)\n * const connected = await ssh.ping()\n * if (!connected.success) throw new Error(connected.error.message)\n * ```\n */\nexport function createSshExecutor(config: SshConfig): SshExecutor {\n /** 密码 helper 与实际 SSH 共用预算;不引入全局凭据缓存或长连接生命周期。 */\n const runAuthenticated = async (command: string, args: string[], options: CommandOptions): Promise<HaiResult<CommandResult>> => {\n if (!usesSshPassword(config))\n return runCommand(command, args, options)\n if (!config.password || (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > 2147483647)))\n return err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM('deploy_sshPasswordInvalid'), ext: { commandExecution: { reason: 'configuration', localTermination: 'not-started' } } })\n const deadline = options.timeoutMs === undefined ? Number.POSITIVE_INFINITY : performance.now() + options.timeoutMs\n const prepared = await prepareSshAskpass(config.password, deadline, options.terminationTimeoutMs)\n if (!prepared.success)\n return prepared\n let result: HaiResult<CommandResult>\n let removed: HaiResult<void> = ok(undefined)\n try {\n const remaining = deadline - performance.now()\n result = remaining <= 0\n ? err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM('deploy_sshAskpassFailed'), ext: { commandExecution: { reason: 'timeout', localTermination: 'not-started' } } })\n : await runCommand(command, args, {\n ...options,\n env: prepared.data.env,\n timeoutMs: Number.isFinite(deadline) ? Math.ceil(remaining) : undefined,\n secrets: [...(options.secrets ?? []), config.password],\n })\n }\n catch {\n result = err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM('deploy_sshAskpassFailed'), ext: { commandExecution: { reason: 'configuration', localTermination: 'unknown' } } })\n }\n finally {\n removed = prepared.data.cleanup()\n }\n if (!removed.success)\n return result.success ? removed : err({ ...result.error, message: `${result.error.message}\\n${removed.error.message}` })\n return result\n }\n\n const exec: SshExecutor['exec'] = async (remoteCommand, options) => {\n const result = await runAuthenticated('ssh', buildSshExecArgs(config, remoteCommand), {\n timeoutMs: options?.timeoutMs,\n terminationTimeoutMs: options?.terminationTimeoutMs,\n maxCaptureChars: options?.maxCaptureChars,\n secrets: options?.secrets,\n onOutput: options?.onOutput,\n })\n if (result.success)\n return result\n const state = getDeployCommandState(result.error)\n // 连接客户端退出并不能证明远端进程结束;只增加安全状态,不暴露远程命令原文。\n return err({ ...result.error, suggestion: deployM('deploy_remoteUnknown'), ext: { ...result.error.ext, commandExecution: { ...state, reason: state?.reason ?? 'exit', localTermination: state?.localTermination ?? 'unknown', remoteExecution: 'unknown' } } })\n }\n\n const upload: SshExecutor['upload'] = async (localPath, remotePath) => {\n const args = buildScpUploadArgs(config, localPath, remotePath)\n const result = await runAuthenticated('scp', args, { timeoutMs: 600_000 })\n if (!result.success) {\n return err({ ...HaiDeployError.IMAGE_TRANSFER_FAILED, message: deployM('deploy_imageTransferFailed', { params: { error: result.error.message } }), ext: result.error.ext })\n }\n return ok(undefined)\n }\n\n const ping: SshExecutor['ping'] = async () => {\n logger.debug('SSH preflight', { host: config.host, port: config.port })\n const result = await exec('true', { timeoutMs: 20_000 })\n if (!result.success) {\n return err({ ...HaiDeployError.REMOTE_CONNECT_FAILED, message: deployM('deploy_remoteConnectFailed', { params: { host: config.host, error: result.error.message } }), ext: result.error.ext })\n }\n return ok(undefined)\n }\n\n return { exec, upload, ping }\n}\n","import type { Buffer } from 'node:buffer'\n/** 完整或增量交付包,包含所选服务需要的全部镜像及跨平台部署入口。 */\nimport type { DeploymentArtifact } from '../deploy-artifact.js'\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport { createHash } from 'node:crypto'\nimport { chmodSync, copyFileSync, createReadStream, createWriteStream, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { Transform } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport { parse } from 'yaml'\nimport { artifactChecksum } from '../deploy-artifact.js'\nimport { deployM } from '../deploy-i18n.js'\nimport { createBackendStateAssets } from './deploy-backend-state.js'\nimport { runCommand } from './deploy-command.js'\nimport { createManagedSecretAssets } from './deploy-managed-secrets.js'\nimport { createApplyScript, createLocalInstallScript, createUploadScripts } from './deploy-scripts.js'\nimport { usesSshPassword } from './deploy-ssh.js'\n\n/**\n * 打包所选服务;完整交付自动导出中间件,服务器启动时禁止联网拉取。\n * @throws Error - 制品、Compose、文件读取、镜像导出或打包失败;包含私有运行环境的 tar 必须按秘密传输与保存。\n * @param options - 本次操作选项;字段含义见各子项。\n * @param options.directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @param options.artifactDir - 已经验证的镜像 tar 与 manifest 所在目录。\n * @param options.artifact - 已通过结构、路径和文件摘要验证的构建清单。\n * @param options.projectName - 已归一化的项目名称。\n * @param options.deploymentId - 本次不可变部署标识,用于结果匹配和发布目录。\n * @param options.environment - 部署环境标识,通常为 prod。\n * @param options.config - 已通过 Schema 解析的 docker-ssh 配置。\n * @param options.runtime - 容器引擎策略;auto 探测可用引擎并优先 Podman。\n * @param options.output - 本次独立交付目录内的最终 tar 输出路径。\n * @param options.selected - 本次选择更新的 Compose 服务。\n * @param options.partial - 是否为增量服务部署;不能据此执行首次全量安装。\n * @param options.middlewareEnv - 应用增量继承的框架 HAI_* dotenv;镜像原生变量从独立文件读取。\n * @param options.healthPaths - 允许执行的应用健康检查路径。\n * @param options.hasWebConfig - 是否挂载公开Nginx配置,包含前后端代理或独立Vite目录路由。\n * @param options.proxyService - 挂载 Nginx 配置的服务;缺省为 web,SSR/API 的存储网关为 gateway。\n * @param options.storageRouting - 自建 S3 非敏感连接/访问配置摘要,阻止增量配置与已装基线不一致。\n * @param options.containerPort - 应用容器的实际监听端口。\n * @param options.httpsAssets - 已校验的 HTTPS 证书与脚本附件。\n * @param options.cacheDirectory - 按镜像内容身份组织的私有归档缓存。\n * @returns tar 路径、手工执行说明及启动脚本名。\n * @example 模块内部上下文\n * ```ts\n * const { readDeploymentArtifact } = await import('../deploy-artifact.js')\n * const artifactDir = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(artifactDir)\n * // directory 已由 Provider 准备好 docker-compose-<版本>.yml 与 .env.runtime。\n * const directory = '.hai/deploy/prod/prepared-id'\n * const result = await createDeploymentBundle({ directory, artifactDir, artifact, projectName: 'shop', deploymentId: 'shop-prod-001', environment: 'prod', config: { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } }, runtime: 'auto', output: '.hai/deploy/shop.tar', selected: ['serv'], partial: false, middlewareEnv: '', healthPaths: ['/health'], hasWebConfig: false, containerPort: 3000 })\n * ```\n */\nexport async function createDeploymentBundle(options: {\n directory: string\n artifactDir: string\n artifact: DeploymentArtifact\n projectName: string\n deploymentId: string\n environment: string\n config: DockerSshProviderConfig\n runtime: 'auto' | 'podman' | 'docker'\n output: string\n selected: string[]\n partial: boolean\n middlewareEnv: string\n healthPaths: string[]\n hasWebConfig: boolean\n proxyService?: 'web' | 'gateway'\n storageRouting?: string\n containerPort: number\n /** HTTPS 附件已在写入交付目录前校验证书与域名。 */\n httpsAssets?: Record<string, string>\n /** 按镜像内容身份复用的本地归档缓存;命中仍核验实际归档。 */\n cacheDirectory?: string\n}): Promise<{ bundlePath: string, instructions: string, startName: string }> {\n const { directory, artifactDir, artifact, projectName, environment, config, selected } = options\n const output = resolve(options.output)\n if (!/^[\\w.+-]+\\.tar(?:\\.gz)?$/.test(basename(output)))\n throw new Error(deployM('deploy_bundleNameInvalid'))\n const staging = mkdtempSync(join(directory, '.bundle-'))\n const temporaryTar = `${output}.partial`\n mkdirSync(dirname(output), { recursive: true, mode: 0o700 })\n chmodSync(staging, 0o700)\n const files: string[] = []\n const fileHashes = new Map<string, string>()\n const put = (file: string, content: string): void => {\n mkdirSync(dirname(join(staging, file)), { recursive: true })\n writeFileSync(join(staging, file), content, { mode: 0o600 })\n files.push(file)\n }\n try {\n mkdirSync(join(staging, 'images'))\n const compose = parse(readFileSync(join(directory, `docker-compose-${artifact.appVersion}.yml`), 'utf8')) as {\n services: Record<string, Record<string, unknown>>\n networks?: Record<string, unknown>\n volumes?: Record<string, unknown>\n }\n const dependencies = new Set<string>()\n const references = new Set<string>()\n for (const name of selected) {\n const service = compose.services[name]\n if (!service)\n throw new Error(deployM('deploy_selectionInvalid', { params: { service: name } }))\n if (typeof service.image === 'string')\n references.add(service.image)\n if (service.depends_on) {\n for (const dependency of Array.isArray(service.depends_on) ? service.depends_on as string[] : Object.keys(service.depends_on))\n dependencies.add(dependency)\n }\n if (service.env_file) {\n service.env_file = name === artifact.primaryService\n ? [`../${options.deploymentId}/.env.runtime`, `../${options.deploymentId}/middleware.env`]\n : [`../${options.deploymentId}/middleware-runtime.env`]\n }\n if (Array.isArray(service.volumes))\n service.volumes = service.volumes.map(mount => typeof mount === 'string' ? mount.replace(/\\.\\/(web\\.conf|request-access\\.yml|tls|https-start\\.sh|renew-https\\.sh|\\.env\\.runtime|middleware\\.env|runtime-env\\.mjs):/g, `../${options.deploymentId}/$1:`) : mount)\n }\n put('compose.json', JSON.stringify({ ...compose, services: Object.fromEntries(selected.map(name => [name, compose.services[name]])) }))\n // 合并入口仅保存 extends 指向;更新服务时整体切换定义,避免旧 env_file/卷列表累加。\n put('compose-entry.json', JSON.stringify({ ...compose, services: Object.fromEntries(selected.map(name => [name, { extends: { file: `../${options.deploymentId}/compose.json`, service: name } }])) }))\n let runtime: 'podman' | 'docker' | undefined\n const imageList: string[] = []\n for (const reference of references) {\n if (!/:[^/:]+$/.test(reference) || /:latest$/i.test(reference))\n throw new Error(deployM('deploy_imageVersionRequired', { params: { image: reference } }))\n const built = artifact.images.find(image => image.imageRef === reference)\n const file = built?.file ?? `middleware-${imageList.length + 1}.tar`\n const destination = join(staging, 'images', file)\n if (built) {\n const checksum = await copyArchive(join(artifactDir, file), destination)\n if (checksum !== built.sha256)\n throw new Error(deployM('deploy_artifactInvalid'))\n fileHashes.set(`images/${file}`, checksum)\n }\n else {\n if (!runtime) {\n const candidates = options.runtime === 'auto' ? ['podman', 'docker'] as const : [options.runtime]\n for (const candidate of candidates) {\n if ((await runCommand(candidate, ['version'])).success) {\n runtime = candidate\n break\n }\n }\n if (!runtime)\n throw new Error(deployM('deploy_bundleRuntimeRequired'))\n }\n let inspected = await runCommand(runtime, ['image', 'inspect', '--format', '{{.Id}}', reference])\n if (!inspected.success) {\n const pulled = await runCommand(runtime, ['pull', reference], { timeoutMs: 600_000 })\n if (!pulled.success)\n throw new Error(pulled.error.message)\n inspected = await runCommand(runtime, ['image', 'inspect', '--format', '{{.Id}}', reference])\n }\n const identity = inspected.success && !inspected.data.stdoutTruncated ? inspected.data.stdout.trim().replace(/^sha256:/, '') : ''\n // 导出的归档保留请求的镜像标签;相同内容的不同引用不能直接共用该归档。\n const cacheIdentity = createHash('sha256').update(identity).update('\\0').update(reference).digest('hex')\n const cache = options.cacheDirectory && /^[a-f0-9]{64}$/.test(identity) ? join(options.cacheDirectory, `${runtime}-${cacheIdentity}.tar`) : undefined\n let checksum: string | undefined\n if (cache && existsSync(cache) && existsSync(`${cache}.sha256`) && lstatSync(cache).isFile() && !lstatSync(cache).isSymbolicLink()) {\n const copied = await copyArchive(cache, destination)\n if (copied === readFileSync(`${cache}.sha256`, 'utf8').trim())\n checksum = copied\n }\n if (!checksum) {\n const saved = await runCommand(runtime, ['save', ...(runtime === 'podman' ? ['--format', 'docker-archive'] : []), '-o', destination, reference], { timeoutMs: 600_000 })\n if (!saved.success)\n throw new Error(saved.error.message)\n checksum = await artifactChecksum(destination)\n if (cache) {\n mkdirSync(dirname(cache), { recursive: true, mode: 0o700 })\n // 不发布半写入缓存;并发打包使用各自的临时文件。\n const temporary = `${cache}.${basename(staging)}`\n try {\n copyFileSync(destination, temporary)\n renameSync(temporary, cache)\n writeFileSync(`${cache}.sha256`, `${checksum}\\n`, { mode: 0o600 })\n }\n finally {\n rmSync(temporary, { force: true })\n }\n }\n }\n fileHashes.set(`images/${file}`, checksum)\n }\n files.push(`images/${file}`)\n imageList.push(`${file} ${reference}`)\n }\n put('.env.runtime', readFileSync(join(directory, '.env.runtime'), 'utf8'))\n if (selected.includes(artifact.primaryService) && existsSync(join(directory, 'request-access.yml')))\n put('request-access.yml', readFileSync(join(directory, 'request-access.yml'), 'utf8'))\n put('middleware.env', options.middlewareEnv)\n if (selected.includes(artifact.primaryService) && !compose.services[artifact.primaryService]?.env_file)\n put('runtime-env.mjs', readFileSync(new URL('./deploy-runtime-env.mjs', import.meta.url), 'utf8'))\n const middlewareRuntime = join(directory, 'middleware-runtime.env')\n const nativeEnvironment = existsSync(middlewareRuntime) ? readFileSync(middlewareRuntime, 'utf8') : ''\n put('middleware-runtime.env', nativeEnvironment)\n for (const [file, content] of Object.entries(createManagedSecretAssets(projectName, nativeEnvironment, compose)))\n put(file, content)\n if (options.hasWebConfig)\n put('web.conf', readFileSync(join(directory, 'web.conf'), 'utf8'))\n for (const [file, content] of Object.entries(options.httpsAssets ?? {}))\n put(file, content)\n put('manifest.json', `${JSON.stringify({ ...artifact, images: artifact.images.filter(image => references.has(image.imageRef)), deploymentId: options.deploymentId, selectedServices: selected, partial: options.partial }, null, 2)}\\n`)\n if (options.hasWebConfig) {\n // 增量部署复用当前 Web 镜像,只覆盖公开代理配置;无需重新构建或打包 Web 镜像。\n put('proxy-entry.json', JSON.stringify({ services: { [options.proxyService ?? 'web']: { volumes: [`../${options.deploymentId}/web.conf:/etc/nginx/conf.d/default.conf:ro`] } } }))\n }\n put('storage-routing', `${options.storageRouting ?? ''}\\n`)\n const httpsFingerprint = config.expose.https ? createHash('sha256').update(JSON.stringify({ ...config.expose.https, certificateFile: undefined, privateKeyFile: undefined, certificate: options.httpsAssets?.['tls/fullchain.pem'] })).digest('hex') : ''\n put('layout', `${config.expose.hostPort}:${options.containerPort}:${options.hasWebConfig ? options.proxyService === 'gateway' ? 'gateway' : 'true' : 'false'}:${artifact.primaryService}:${options.hasWebConfig ? await artifactChecksum(join(directory, 'web.conf')) : ''}${httpsFingerprint ? `:${httpsFingerprint}` : ''}\\n`)\n put('web-base-path', `${artifact.webBasePath ?? ''}\\n`)\n put('health-paths', `${options.healthPaths.join('\\n')}\\n`)\n put('image-list', `${imageList.join('\\n')}\\n`)\n put('dependencies', `${[...dependencies].join('\\n')}\\n`)\n // 卷身份和引擎随校验和交付;服务器持久账本不会随暂时移除服务而删除。\n for (const [file, content] of Object.entries(createBackendStateAssets(projectName, compose, selected)))\n put(file, content)\n put('apply.sh', createApplyScript({ deploymentId: options.deploymentId, projectName, environment, directory: `${config.remote.baseDir}/${projectName}`, runtime: config.remote.runtime, partial: options.partial, selected, primaryService: artifact.primaryService, hostPort: config.expose.hostPort, healthPaths: options.healthPaths }))\n const instructionParams = { file: basename(output), start: 'apply.sh', images: [...references].join('\\n'), compose: 'compose.json' }\n const mode = deployM(options.partial ? 'deploy_bundlePartial' : 'deploy_bundleFull')\n const selection = deployM('deploy_bundleSelection', { params: { mode, services: selected.join(', ') } })\n const instructions = `${selection}\\n${deployM('deploy_bundleInstructions', { params: instructionParams })}`\n const readme = `${deployM('deploy_bundleMetadata', { params: { version: artifact.appVersion, buildId: artifact.buildId, deploymentId: options.deploymentId, compose: 'compose.json' } })}\\n${instructions}\\n`\n const checksums = []\n for (const file of files)\n checksums.push(`${fileHashes.get(file) ?? await artifactChecksum(join(staging, file))} ${file}`)\n writeFileSync(join(staging, 'SHA256SUMS'), `${checksums.join('\\n')}\\n`)\n const tar = await runCommand('tar', [output.endsWith('.gz') ? '-czf' : '-cf', temporaryTar, '-C', staging, '.'])\n if (!tar.success)\n throw new Error(tar.error.message)\n chmodSync(temporaryTar, 0o600)\n renameSync(temporaryTar, output)\n const upload = createUploadScripts()\n const scripts = directory\n // 部署配置、清单和镜像只保存在 tar 中,外层仅保留实际入口、目标与说明。\n writeFileSync(join(scripts, 'deploy.sh'), upload.sh, { mode: 0o700 })\n writeFileSync(join(scripts, 'deploy-local.sh'), createLocalInstallScript({ bundle: basename(output), directory: `${config.remote.baseDir}/${projectName}` }), { mode: 0o700 })\n writeFileSync(join(scripts, 'deploy.ps1'), upload.ps1)\n writeFileSync(join(scripts, 'read-target.awk'), upload.reader)\n const target = {\n host: config.ssh?.host ?? 'SERVER_HOST',\n port: config.ssh?.port ?? 22,\n username: config.ssh?.username ?? 'deploy',\n auth: config.ssh && usesSshPassword(config.ssh) ? 'password' : 'key',\n passwordEnv: 'HAI_DEPLOY_PROVIDER_SSH_PASSWORD',\n identityFile: config.ssh?.identityFile ?? '',\n knownHostsFile: config.ssh?.knownHostsFile ?? '',\n strictHostKeyChecking: config.ssh?.strictHostKeyChecking ?? true,\n connectTimeoutSeconds: config.ssh?.connectTimeoutSeconds ?? 10,\n directory: `${config.remote.baseDir}/${projectName}`,\n bundle: basename(output),\n }\n const comments = {\n host: deployM('deploy_targetHost'),\n port: deployM('deploy_targetPort'),\n username: deployM('deploy_targetUsername'),\n auth: deployM('deploy_targetAuth'),\n passwordEnv: deployM('deploy_targetPasswordEnv'),\n identityFile: deployM('deploy_targetIdentityFile'),\n knownHostsFile: deployM('deploy_targetKnownHostsFile'),\n strictHostKeyChecking: deployM('deploy_targetStrictHostKeyChecking'),\n connectTimeoutSeconds: deployM('deploy_targetConnectTimeoutSeconds'),\n directory: deployM('deploy_targetDirectory'),\n bundle: deployM('deploy_targetBundle'),\n }\n writeFileSync(join(scripts, 'deploy-target.json'), `${JSON.stringify({ ...target, _comments: comments }, null, 2)}\\n`)\n writeFileSync(join(scripts, 'README.txt'), readme)\n for (const file of [`docker-compose-${artifact.appVersion}.yml`, '.env.runtime', 'middleware-runtime.env', 'request-access.yml', ...(options.hasWebConfig ? ['web.conf'] : [])])\n rmSync(join(directory, file), { force: true })\n return { bundlePath: output, instructions: `${selection}\\n${deployM('deploy_bundleInstructions', { params: { ...instructionParams, file: output } })}\\n${scripts}`, startName: 'apply.sh' }\n }\n finally {\n rmSync(staging, { recursive: true, force: true })\n rmSync(temporaryTar, { force: true })\n }\n}\n\n/** 复制与计算摘要共用一次顺序读取,避免每个大镜像复制后再读取一遍。 */\nasync function copyArchive(source: string, destination: string): Promise<string> {\n const hash = createHash('sha256')\n const digest = new Transform({\n transform(chunk: Buffer, _encoding, callback) {\n hash.update(chunk)\n callback(null, chunk)\n },\n })\n await pipeline(createReadStream(source), digest, createWriteStream(destination, { mode: 0o600 }))\n return hash.digest('hex')\n}\n","/** HTTPS 的证书交付、Nginx 入口和 Certbot 生命周期;所有应用类型共用。 */\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport { createPrivateKey, createPublicKey, X509Certificate } from 'node:crypto'\nimport { readFileSync, statSync } from 'node:fs'\nimport { isIP } from 'node:net'\nimport { resolve } from 'node:path'\nimport { deployM } from '../deploy-i18n.js'\nimport { shellArgument } from './deploy-scripts.js'\n\n/**\n * 官方 Certbot 客户端的固定版本,随离线包导出,目标服务器不拉取镜像。\n * @example 模块内部上下文\n * ```ts\n * const certbotImage = CERTBOT_IMAGE\n * ```\n */\nexport const CERTBOT_IMAGE = 'docker.io/certbot/certbot:v5.9.0'\n/**\n * Docker SSH 入口已校验的 HTTPS 配置。\n * @example 模块内部上下文\n * ```ts\n * const https: HttpsConfig = { type: 'files', domain: 'app.example.com', port: 443, redirectHttp: true, certificateFile: './tls/fullchain.pem', privateKeyFile: './tls/privkey.pem' }\n * ```\n */\ntype HttpsConfig = NonNullable<DockerSshProviderConfig['expose']['https']>\n\n/**\n * 校验本地 PEM 并生成受保护的部署附件;异常不包含证书或私钥原文。\n * @param config - 已解析的 HTTPS 设置。\n * @param projectDirectory - 相对证书路径的工程根。\n * @returns 包内附件;私钥只能保存到私密交付目录,不能复制到构建上下文。\n * @example 模块内部上下文\n * ```ts\n * // 申请脚本由实际 HTTPS 配置生成,不在示例中请求证书。\n * const assets = createHttpsAssets({ type: 'letsencrypt', domain: 'app.example.com', port: 443, redirectHttp: true, email: 'ops@example.com', acceptTerms: true }, '.')\n * ```\n */\nexport function createHttpsAssets(config: HttpsConfig, projectDirectory: string): Record<string, string> {\n const assets: Record<string, string> = {\n https: `${config.domain} ${config.port} ${config.type}\\n`,\n }\n if (config.type === 'files') {\n try {\n const readPem = (file: string): string => {\n const path = resolve(projectDirectory, file)\n if (!statSync(path).isFile() || statSync(path).size > 1048576)\n throw new Error('Invalid PEM file')\n return readFileSync(path, 'utf8')\n }\n const certificate = readPem(config.certificateFile)\n const key = readPem(config.privateKeyFile)\n const parsed = new X509Certificate(certificate)\n const publicKey = createPublicKey(createPrivateKey(key)).export({ type: 'spki', format: 'der' })\n const now = Date.now()\n if (!publicKey.equals(parsed.publicKey.export({ type: 'spki', format: 'der' }))\n || now < Date.parse(parsed.validFrom) || now >= Date.parse(parsed.validTo)\n || !(isIP(config.domain) ? parsed.checkIP(config.domain) : parsed.checkHost(config.domain))) {\n throw new Error('Certificate validation failed')\n }\n assets['tls/fullchain.pem'] = certificate\n assets['tls/privkey.pem'] = key\n }\n catch {\n throw new Error(deployM('deploy_httpsCertificateInvalid'))\n }\n }\n else {\n assets['renew-https.sh'] = createRenewScript(config)\n }\n assets['prepare-https.sh'] = createPrepareScript(config)\n assets['https-start.sh'] = String.raw`#!/bin/sh\nset -eu\n# 目录挂载允许原子替换证书;只有新证书通过 nginx -t 才重载。\nwatch_certificate() {\n previous=$(sha256sum /etc/nginx/tls/fullchain.pem)\n while sleep 60; do\n current=$(sha256sum /etc/nginx/tls/fullchain.pem) || continue\n if [ \"$previous\" != \"$current\" ]; then\n if nginx -t && nginx -s reload; then previous=$current; else printf '[ERROR] HTTPS certificate reload failed\\n' >&2; fi\n fi\n done\n}\nwatch_certificate &\nexec /docker-entrypoint.sh nginx -g 'daemon off;'\n`\n return assets\n}\n\n/**\n * 为已有静态/反向代理配置添加 TLS;健康检查和 ACME 挑战仍可通过内部 HTTP 入口访问。\n * @param source - 已校验的、仅含一个入口 server 的 Nginx 配置。\n * @param config - HTTPS 设置。\n * @param httpPort - Nginx 容器内原有监听端口。\n * @returns TLS 入口与 HTTP 跳转/挑战配置。\n * @example 模块内部上下文\n * ```ts\n * const https: HttpsConfig = { type: 'files', domain: 'app.example.com', port: 443, redirectHttp: true, certificateFile: './tls/fullchain.pem', privateKeyFile: './tls/privkey.pem' }\n * const nginx = renderHttpsProxy('server { listen 8080; server_name _; }', https, 8080)\n * ```\n */\nexport function renderHttpsProxy(source: string, config: HttpsConfig, httpPort: number): string {\n const publicPort = config.port === 443 ? '' : `:${config.port}`\n const challenge = ' location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; }\\n'\n const tls = source\n .replace(`listen ${httpPort};`, `listen ${httpPort === 8443 ? 8444 : 8443} ssl;\\n ssl_certificate /etc/nginx/tls/fullchain.pem;\\n ssl_certificate_key /etc/nginx/tls/privkey.pem;`)\n .replace('server_name _;', `server_name ${config.domain};`)\n .replaceAll('proxy_set_header X-Forwarded-Proto $scheme;', 'proxy_set_header X-Forwarded-Proto https;')\n const http = config.redirectHttp\n ? `server {\\n listen ${httpPort};\\n server_name ${config.domain};\\n${challenge} location ~ ^/_hai/(web-health|gateway-health)$ { access_log off; return 200 'ok'; }\\n location / { return 308 https://${config.domain}${publicPort}$request_uri; }\\n}\\n`\n : source.slice(source.indexOf('server {')).replace('server_name _;', `server_name ${config.domain};\\n${challenge}`)\n return `${tls}\\n${http}`\n}\n\n/** 签发成功后才覆盖公开目录;目录上层为 0700,Nginx 只读挂载证书子目录。 */\nconst publishCertificate = String.raw`publish_certificate() {\n certificate=\"/etc/letsencrypt/live/$domain\"\n test -s \"$certificate/fullchain.pem\" && test -s \"$certificate/privkey.pem\"\n cp \"$certificate/fullchain.pem\" /output/fullchain.pem.next\n cp \"$certificate/privkey.pem\" /output/privkey.pem.next\n chmod 444 /output/fullchain.pem.next /output/privkey.pem.next\n mv /output/privkey.pem.next /output/privkey.pem\n mv /output/fullchain.pem.next /output/fullchain.pem\n}\n`\n\nfunction createRenewScript(config: Extract<HttpsConfig, { type: 'letsencrypt' }>): string {\n return `#!/bin/sh\\nset -eu\\ndomain=${shellArgument(config.domain)}\\n${publishCertificate}${String.raw`\ntrap 'exit 0' TERM INT\n# Certbot 自己判断到期时间;同一官方客户端同时负责申请与续期,不实现 ACME 协议。\nwhile :; do\n if certbot renew --cert-name \"$domain\" --non-interactive; then\n if [ -s \"/etc/letsencrypt/live/$domain/fullchain.pem\" ]; then\n current=$(sha256sum \"/etc/letsencrypt/live/$domain/fullchain.pem\" | awk '{print $1}')\n installed=$(sha256sum /output/fullchain.pem | awk '{print $1}')\n if [ \"$current\" != \"$installed\" ]; then publish_certificate; fi\n fi\n else\n printf '[ERROR] Certbot renewal failed; the existing certificate remains installed\\n' >&2\n fi\n sleep 43200 & wait $! || exit 0\ndone\n`}`\n}\n\nfunction createPrepareScript(config: HttpsConfig): string {\n const header = `#!/bin/sh\\nset -eu\\numask 077\\nroot=$1\\nrelease=$2\\nruntime=$3\\nmode=$4\\ndomain=${shellArgument(config.domain)}\\n`\n if (config.type === 'files') {\n return header + String.raw`\ntest \"$mode\" != prepare || {\n # 宿主 root/release 保持私密;容器仅可读取独立挂载的证书目录。\n chmod 700 \"$root\" \"$release\"\n chmod 755 \"$release/tls\"\n chmod 444 \"$release/tls/fullchain.pem\" \"$release/tls/privkey.pem\"\n}\n`\n }\n const python = [\n 'from cryptography import x509',\n 'from cryptography.x509.oid import NameOID',\n 'from cryptography.hazmat.primitives import hashes, serialization',\n 'from cryptography.hazmat.primitives.asymmetric import ec',\n 'from datetime import datetime, timedelta, timezone',\n 'from pathlib import Path',\n 'import sys',\n 'name=sys.argv[1]',\n 'key=ec.generate_private_key(ec.SECP256R1())',\n 'subject=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,name)])',\n 'now=datetime.now(timezone.utc)',\n 'cert=x509.CertificateBuilder().subject_name(subject).issuer_name(subject).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=1)).not_valid_after(now+timedelta(days=1)).add_extension(x509.SubjectAlternativeName([x509.DNSName(name)]),False).sign(key,hashes.SHA256())',\n 'Path(\"/output/privkey.pem\").write_bytes(key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))',\n 'Path(\"/output/fullchain.pem\").write_bytes(cert.public_bytes(serialization.Encoding.PEM))',\n ].join('\\n')\n const publish = `set -eu\\ndomain=${shellArgument(config.domain)}\\n${publishCertificate}\\npublish_certificate\\n`\n return `${header}image=${shellArgument(CERTBOT_IMAGE)}\\nemail=${shellArgument(config.email)}\\nbootstrap=${shellArgument(python)}\\n${String.raw`\nstate=\"$root/https\"\ncertificates=\"$state/certificates/$domain\"\nmkdir -p \"$state/acme\" \"$state/webroot\" \"$certificates\"\nchmod 700 \"$root\" \"$state\" \"$state/acme\"\nchmod 755 \"$state/webroot\" \"$certificates\"\nif [ \"$mode\" = prepare ]; then\n if [ ! -s \"$certificates/fullchain.pem\" ] || [ ! -s \"$certificates/privkey.pem\" ]; then\n if [ \"$5\" = true ]; then printf 'HTTPS certificate state missing; create a full deployment.\\n' >&2; exit 1; fi\n # 临时证书只用于启动挑战入口;签发失败不得提交 current。\n \"$runtime\" run --rm --pull never --entrypoint python -v \"$certificates:/output\" \"$image\" -c \"$bootstrap\" \"$domain\"\n chmod 444 \"$certificates/fullchain.pem\" \"$certificates/privkey.pem\"\n fi\nelif [ \"$mode\" = issue ]; then\n \"$runtime\" run --rm --pull never -v \"$state/acme:/etc/letsencrypt\" -v \"$state/webroot:/var/www/certbot\" \"$image\" certonly --webroot --webroot-path /var/www/certbot --cert-name \"$domain\" --domain \"$domain\" --email \"$email\" --agree-tos --non-interactive --keep-until-expiring\n \"$runtime\" run --rm --pull never --entrypoint sh -v \"$state/acme:/etc/letsencrypt:ro\" -v \"$certificates:/output\" \"$image\" -c `}${shellArgument(publish)}\\nfi\\n`\n}\n","/**\n * @h-ai/deploy — 容器编排文件生成\n *\n * 根据应用扫描结果生成 compose 文件与运行期环境:按需为 db/cache/storage\n * 追加自建 sidecar 服务,并注入对应的 HAI_DB / HAI_CACHE / HAI_STORAGE 覆盖变量。\n * 敏感值仅写入受保护的环境文件,应用与中间件分开,禁止进入 compose 文件。\n * @module deploy-container-compose\n */\n\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport type { DeployAppOptions, ScanResult, ServiceType } from '../deploy-types.js'\nimport { randomBytes } from 'node:crypto'\nimport { TrustedProxiesSchema } from '@h-ai/core'\nimport { resolveTransportBodyLimits } from '@h-ai/crypto'\nimport { stringify } from 'yaml'\nimport { mergeEnvironmentLayers } from '../deploy-environment.js'\nimport { usesDefaultMiddleware } from '../deploy-functions.js'\nimport { mergeManagedMiddlewareConfig } from '../deploy-middleware-config.js'\nimport { CERTBOT_IMAGE } from './deploy-https.js'\n\n/** sidecar 镜像固定版本,避免 `:latest` 漂移导致行为变化。 */\nconst IMAGES = {\n postgres: 'docker.io/library/postgres:16.15-alpine',\n mysql: 'docker.io/library/mysql:8.4.11',\n redis: 'docker.io/library/redis:7.4.11-alpine',\n rustfs: 'ghcr.io/rustfs/rustfs:1.0.1',\n minio: 'ghcr.io/coollabsio/minio:RELEASE.2025-10-15T17-29-55Z',\n qdrant: 'docker.io/qdrant/qdrant:v1.19.2',\n pgvector: 'docker.io/pgvector/pgvector:0.8.0-pg17',\n chroma: 'docker.io/chromadb/chroma:1.5.5',\n ldap: 'docker.io/osixia/openldap:1.5.0',\n smtp: 'docker.io/axllent/mailpit:v1.27.4',\n nginx: 'docker.io/nginxinc/nginx-unprivileged:1.29.8-alpine',\n} as const\n\n// 旧版本曾把镜像原生变量保存到应用环境;读取旧配置时也不再传给业务容器。\nconst CONTAINER_ENV_KEYS = new Set([\n 'POSTGRES_USER',\n 'POSTGRES_PASSWORD',\n 'POSTGRES_DB',\n 'MYSQL_ROOT_PASSWORD',\n 'MYSQL_DATABASE',\n 'MYSQL_USER',\n 'MYSQL_PASSWORD',\n 'MINIO_ROOT_USER',\n 'MINIO_ROOT_PASSWORD',\n 'RUSTFS_ACCESS_KEY',\n 'RUSTFS_SECRET_KEY',\n 'RUSTFS_ADDRESS',\n 'RUSTFS_VOLUMES',\n 'RUSTFS_CONSOLE_ENABLE',\n 'LDAP_DOMAIN',\n 'LDAP_ORGANISATION',\n 'LDAP_ADMIN_PASSWORD',\n 'LDAP_TLS',\n])\n\n/**\n * compose 服务定义(结构化对象,交由 yaml 序列化)。\n * 内部 Compose 文档对象,不是公开部署配置 Schema。\n * @example 模块内部上下文\n * ```ts\n * const service: ComposeService = { image: 'registry.example.org/shop:1.0.0', ports: ['8080:3000'] }\n * ```\n */\ntype ComposeService = Record<string, unknown>\n\n/**\n * sidecar 规划结果。\n * 无中间件应用的空计划是合法输入;有连接时 env/secrets 可能含私密值,不能整体展示。\n * @example 模块内部上下文\n * ```ts\n * const sidecar: SidecarPlan = { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, containerEnv: {}, dependsOn: [], secrets: [] }\n * const yaml = generateComposeFile({ projectName: 'shop', appVersion: '1.0.0', imageRef: 'shop:1.0.0-build1', hostPort: 8080, containerPort: 3000, sidecar })\n * ```\n */\nexport interface SidecarPlan {\n /** 实际启用的自建服务 */\n services: ServiceType[]\n /** compose services 片段(不含 app) */\n composeServices: Record<string, ComposeService>\n /** 命名卷 */\n volumes: Record<string, unknown>\n /** 挂载到 主应用容器的卷(如 sqlite/lancedb 的本地数据目录持久化) */\n appVolumes: string[]\n /** 框架 HAI_* 配置,允许保存到工程环境并注入应用。 */\n env: Record<string, string>\n /** 镜像要求的原生变量,仅写 middleware-runtime.env 并注入中间件。 */\n containerEnv: Record<string, string>\n /** serv 服务的 depends_on 列表 */\n dependsOn: string[]\n /** 需要在日志中脱敏的敏感值 */\n secrets: string[]\n}\n\n/**\n * 运行期环境构建结果。\n * @example 模块内部上下文\n * ```ts\n * const plan: RuntimeEnvPlan = { env: { NODE_ENV: 'production' }, sidecar: { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, containerEnv: {}, dependsOn: [], secrets: [] } }\n * const content = serializeEnvFile(plan.env)\n * ```\n */\nexport interface RuntimeEnvPlan {\n /** 完整运行期环境(写入 .env.runtime) */\n env: Record<string, string>\n /** sidecar 规划 */\n sidecar: SidecarPlan\n}\n\n/** 生成随机密码(url 安全)。 */\nfunction generatePassword(): string {\n return randomBytes(24).toString('base64url')\n}\n\n/**\n * 生成首次部署的候选值,不读取或创建打包机长期凭据缓存。\n * 服务器 apply 阶段以项目自己的私有状态定稿,后续电脑生成的候选不会改密码。\n * @returns 本包的私有候选值。\n */\nfunction createSidecarCandidates(): Record<string, string> {\n return {\n dbPassword: generatePassword(),\n storagePassword: generatePassword(),\n ldapPassword: generatePassword(),\n }\n}\n\n/** 为 app 追加本地数据卷(sqlite / lancedb 等文件型后端持久化)。 */\nfunction addAppDataVolume(plan: SidecarPlan, projectName: string): void {\n const mount = `${projectName}-data:/app/data`\n if (!plan.appVolumes.includes(mount)) {\n plan.appVolumes.push(mount)\n plan.volumes[`${projectName}-data`] = null\n }\n}\n\n/** PostgreSQL sidecar。 */\nfunction planPostgresDb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('db')\n plan.dependsOn.push('db')\n plan.composeServices.db = {\n image: IMAGES.postgres,\n container_name: `hai-${projectName}-db`,\n restart: 'unless-stopped',\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-db-data:/var/lib/postgresql/data`],\n healthcheck: { test: ['CMD', 'pg_isready', '-h', '127.0.0.1', '-U', 'hai', '-d', 'hai'], interval: '2s', timeout: '5s', retries: 60 },\n networks: net,\n }\n plan.volumes[`${projectName}-db-data`] = null\n plan.containerEnv.POSTGRES_USER = 'hai'\n plan.containerEnv.POSTGRES_PASSWORD = password\n plan.containerEnv.POSTGRES_DB = 'hai'\n plan.env.HAI_DB = JSON.stringify({ type: 'postgresql', url: `postgresql://hai:${password}@db:5432/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** MySQL sidecar。 */\nfunction planMysqlDb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('db')\n plan.dependsOn.push('db')\n plan.composeServices.db = {\n image: IMAGES.mysql,\n container_name: `hai-${projectName}-db`,\n restart: 'unless-stopped',\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-db-data:/var/lib/mysql`],\n healthcheck: { test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --silent'], interval: '2s', timeout: '5s', retries: 60 },\n networks: net,\n }\n plan.volumes[`${projectName}-db-data`] = null\n plan.containerEnv.MYSQL_ROOT_PASSWORD = password\n plan.containerEnv.MYSQL_DATABASE = 'hai'\n plan.containerEnv.MYSQL_USER = 'hai'\n plan.containerEnv.MYSQL_PASSWORD = password\n plan.env.HAI_DB = JSON.stringify({ type: 'mysql', url: `mysql://hai:${password}@db:3306/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** Redis sidecar。 */\nfunction planRedisCache(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('cache')\n plan.dependsOn.push('cache')\n plan.composeServices.cache = {\n image: IMAGES.redis,\n container_name: `hai-${projectName}-cache`,\n restart: 'unless-stopped',\n healthcheck: { test: ['CMD', 'redis-cli', 'ping'], interval: '2s', timeout: '5s', retries: 60 },\n networks: net,\n }\n plan.env.HAI_CACHE = JSON.stringify({ type: 'redis', url: 'redis://cache:6379' })\n}\n\n/** S3 协议与服务实现分离;RustFS/MinIO 使用相同应用契约及幂等 bucket 初始化。 */\nfunction planS3Storage(plan: SidecarPlan, projectName: string, password: string, net: string[], engine: 'rustfs' | 'minio', configured: Record<string, unknown> = {}): void {\n plan.services.push('storage')\n plan.dependsOn.push('storage')\n plan.composeServices.storage = {\n image: IMAGES[engine],\n container_name: `hai-${projectName}-storage`,\n restart: 'unless-stopped',\n ...(engine === 'minio' ? { command: ['server', '/data'] } : {}),\n healthcheck: { test: engine === 'rustfs' ? ['CMD', 'curl', '--noproxy', '*', '-fsS', 'http://127.0.0.1:9000/minio/health/ready'] : ['CMD', 'mc', 'ready', 'http://127.0.0.1:9000'], interval: '2s', timeout: '5s', retries: 60 },\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-storage-data:/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-storage-data`] = null\n if (engine === 'rustfs') {\n Object.assign(plan.containerEnv, { RUSTFS_ACCESS_KEY: 'hai-storage', RUSTFS_SECRET_KEY: password, RUSTFS_ADDRESS: '0.0.0.0:9000', RUSTFS_VOLUMES: '/data', RUSTFS_CONSOLE_ENABLE: 'false' })\n }\n else {\n Object.assign(plan.containerEnv, { MINIO_ROOT_USER: 'hai-storage', MINIO_ROOT_PASSWORD: password })\n }\n plan.env.HAI_STORAGE = JSON.stringify({\n type: 's3',\n endpoint: 'http://storage:9000',\n bucket: configured.bucket || 'hai',\n region: configured.region || 'us-east-1',\n // 自建只替换连接和托管凭据,不能丢失对象前缀、外部签名地址或操作日志策略。\n ...Object.fromEntries(['prefix', 'publicEndpoint', 'publicUrl', 'operationLog'].filter(name => configured[name] !== undefined).map(name => [name, configured[name]])),\n accessKeyId: 'hai-storage',\n secretAccessKey: password,\n forcePathStyle: true,\n createBucket: true,\n })\n plan.env.HAI_STORAGE_CREATEBUCKET = 'true'\n plan.secrets.push(password)\n}\n\n/** Qdrant 向量库 sidecar。 */\nfunction planQdrantVecdb(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.qdrant,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n volumes: [`${projectName}-vecdb-data:/qdrant/storage`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n plan.env.HAI_VECDB = JSON.stringify({ type: 'qdrant', url: 'http://vecdb:6333' })\n}\n\n/** pgvector 向量库 sidecar(PostgreSQL + pgvector 扩展)。 */\nfunction planPgvectorVecdb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.pgvector,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-vecdb-data:/var/lib/postgresql/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n // 与 postgres db sidecar 共用 POSTGRES_* 凭据(不同实例、不同卷,值一致即可)。\n plan.containerEnv.POSTGRES_USER = 'hai'\n plan.containerEnv.POSTGRES_PASSWORD = password\n plan.containerEnv.POSTGRES_DB = 'hai'\n plan.env.HAI_VECDB = JSON.stringify({ type: 'pgvector', url: `postgresql://hai:${password}@vecdb:5432/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** Chroma 向量库 sidecar。 */\nfunction planChromaVecdb(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.chroma,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n volumes: [`${projectName}-vecdb-data:/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n plan.env.HAI_VECDB = JSON.stringify({ type: 'chroma', url: 'http://vecdb:8000' })\n}\n\n/**\n * 解析 keep 策略;保留内部连接仍交付对应 sidecar,未选择的服务保持不变。\n * @param scan - 实际配置扫描结果。\n * @param options - 本次部署策略。\n * @returns 与执行端共用的有效策略,不读写文件或凭据。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const options = resolveSidecarOptions(scanned.data, { serviceModes: { db: 'keep' } })\n * ```\n */\nexport function resolveSidecarOptions(scan: ScanResult, options?: DeployAppOptions): DeployAppOptions {\n // 保持配置不变仍需交付自建服务镜像;已保存的容器服务地址可明确区分外部连接。\n const serviceModes = { ...options?.serviceModes }\n for (const requirement of scan.middlewares ?? []) {\n // 规划描述完整拓扑;selectedServices 只限制后续归档和更新,不能让未选自建依赖消失。\n const mode = serviceModes[requirement.envPrefix] ?? serviceModes[requirement.service]\n if (mode !== 'keep')\n continue\n const endpoint = requirement.config.url ?? requirement.config.endpoint\n let host = requirement.config.host\n if (typeof endpoint === 'string') {\n try {\n host = new URL(endpoint).hostname\n }\n catch {\n continue\n }\n }\n if (host === requirement.service || ['sqlite', 'local', 'memory', 'lancedb'].includes(requirement.backend)) {\n serviceModes[requirement.envPrefix] = 'default'\n serviceModes[requirement.service] = 'default'\n }\n }\n return { ...options, serviceModes }\n}\n\n/**\n * 复用实际编排规则生成 sidecar;secretValues 仅供只读计划提供空占位值,执行时生成私有候选。\n * 仅为 requiredServices 中采用 default 且无 Provisioner 配置的服务规划匹配后端;文件后端共用 app 数据卷。\n * @param _appDir - 调用方应用目录上下文;凭据不在此落盘。\n * @param projectName - 部署项目身份。\n * @param scan - 实际依赖与配置扫描结果。\n * @param provisionEnv - 已开通服务的环境变量。\n * @param options - 执行选项。\n * @param s3Engine - S3 服务实现。\n * @param secretValues - 内部规划的凭据占位值,不是公开配置。\n * @returns sidecar 计划,env 和 secrets 不得整体输出。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const sidecar = planSidecars(process.cwd(), 'shop', scanned.data, {}, { serviceModes: { db: 'keep' } })\n * ```\n */\nexport function planSidecars(\n _appDir: string,\n projectName: string,\n scan: ScanResult,\n provisionEnv: Record<string, string>,\n options?: DeployAppOptions,\n s3Engine: 'rustfs' | 'minio' = 'rustfs',\n secretValues?: Record<string, string>,\n): SidecarPlan {\n options = resolveSidecarOptions(scan, options)\n const plan: SidecarPlan = {\n services: [],\n composeServices: {},\n volumes: {},\n appVolumes: [],\n env: {},\n containerEnv: {},\n dependsOn: [],\n secrets: [],\n }\n // 全部保持不变时,不生成自建中间件候选。\n if (!scan.requiredServices.some(service => usesDefaultMiddleware(scan, service, options)))\n return plan\n const secrets = secretValues ?? createSidecarCandidates()\n const net = ['hai-app']\n const backends = scan.serviceBackends\n\n for (const service of scan.requiredServices) {\n if (!usesDefaultMiddleware(scan, service, options))\n continue\n if (service === 'db' && !provisionEnv.HAI_DB) {\n const backend = backends.db ?? 'postgresql'\n if (backend === 'mysql')\n planMysqlDb(plan, projectName, secrets.dbPassword, net)\n else if (backend === 'sqlite')\n addAppDataVolume(plan, projectName) // 文件库:仅持久化数据目录,保留应用自身 sqlite 配置\n else\n planPostgresDb(plan, projectName, secrets.dbPassword, net)\n }\n else if (service === 'cache' && !provisionEnv.HAI_CACHE) {\n if ((backends.cache ?? 'redis') === 'redis')\n planRedisCache(plan, projectName, net)\n }\n else if (service === 'storage' && !provisionEnv.HAI_STORAGE) {\n if ((backends.storage ?? 's3') === 's3')\n planS3Storage(plan, projectName, secrets.storagePassword, net, s3Engine, scan.middlewares?.find(item => item.service === 'storage')?.config)\n else\n addAppDataVolume(plan, projectName)\n }\n else if (service === 'vecdb' && !provisionEnv.HAI_VECDB) {\n const backend = backends.vecdb ?? 'qdrant'\n if (backend === 'pgvector')\n planPgvectorVecdb(plan, projectName, secrets.dbPassword, net)\n else if (backend === 'chroma')\n planChromaVecdb(plan, projectName, net)\n else if (backend === 'lancedb')\n addAppDataVolume(plan, projectName) // 嵌入式:持久化本地向量文件\n else\n planQdrantVecdb(plan, projectName, net)\n }\n else if (service === 'ldap' && backends.ldap === 'ldap' && !provisionEnv.HAI_IAM_LDAP) {\n const password = secrets.ldapPassword ?? secrets.dbPassword\n plan.services.push('ldap')\n plan.dependsOn.push('ldap')\n plan.composeServices.ldap = { image: IMAGES.ldap, restart: 'unless-stopped', env_file: ['middleware-runtime.env'], networks: net, volumes: [`${projectName}-ldap-data:/var/lib/ldap`, `${projectName}-ldap-config:/etc/ldap/slapd.d`] }\n plan.volumes[`${projectName}-ldap-data`] = null\n plan.volumes[`${projectName}-ldap-config`] = null\n Object.assign(plan.containerEnv, { LDAP_DOMAIN: 'example.org', LDAP_ORGANISATION: 'HAI', LDAP_ADMIN_PASSWORD: password, LDAP_TLS: 'false' })\n Object.assign(plan.env, { HAI_IAM_LOGIN_LDAP: 'true', HAI_IAM_LDAP: JSON.stringify({ url: 'ldap://ldap:389', bindDn: 'cn=admin,dc=example,dc=org', bindPassword: password, searchBase: 'dc=example,dc=org' }) })\n plan.secrets.push(password)\n }\n else if (service === 'email' && (scan.middlewares ? scan.middlewares.some(item => item.service === 'email' && item.backend === 'smtp' && (options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.email ?? 'default') === 'default') : backends.email === 'smtp') && !provisionEnv.HAI_REACH_PROVIDERS) {\n plan.services.push('email')\n plan.dependsOn.push('email')\n plan.composeServices.email = { image: IMAGES.smtp, restart: 'unless-stopped', networks: net }\n const requirements = scan.middlewares?.filter(item => item.service === 'email' && item.backend === 'smtp' && ['default', undefined].includes(options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.email))\n if (requirements?.length) {\n for (const requirement of requirements)\n plan.env[requirement.envPrefix] = JSON.stringify({ name: requirement.config.name ?? 'email', type: 'smtp', host: 'email', port: 1025, secure: false, from: requirement.config.from || 'noreply@example.com' })\n }\n else if (!scan.middlewares) {\n plan.env.HAI_REACH_PROVIDERS_0 = JSON.stringify({ name: 'email', type: 'smtp', host: 'email', port: 1025, secure: false, from: 'noreply@example.com' })\n }\n }\n }\n\n for (const requirement of scan.middlewares ?? []) {\n const supplied = plan.env[requirement.envPrefix]\n if (supplied)\n plan.env[requirement.envPrefix] = JSON.stringify(mergeManagedMiddlewareConfig(requirement, JSON.parse(supplied)))\n }\n return plan\n}\n\n/**\n * 构建运行期环境变量并规划 sidecar。\n *\n * 合并顺序(后者覆盖前者):目标环境默认 < 应用显式配置 < sidecar 自建 < Provisioner 输出。\n * NODE_ENV 默认按目标模式选择:dev/development 为 development,test 为 test,其余为 production。\n * @param appDir - 应用根目录\n * @param projectName - 项目名\n * @param scan - 扫描结果\n * @param provisionEnv - Provisioner 输出环境变量\n * @param containerPort - 容器内监听端口\n * @returns 运行期环境与 sidecar 规划\n * @param options - 本次操作选项;字段含义见各子项。\n * @param appEnv - 已加载的应用变量,和云开通结果分别传入。\n * @param s3Engine - 自建 S3 服务实现;协议仍为 s3,默认 rustfs。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const plan = buildRuntimeEnv(process.cwd(), 'shop', scanned.data, {}, 3000, { environment: 'prod' }, { NODE_ENV: 'production' })\n * const text = serializeEnvFile(plan.env)\n * ```\n */\nexport function buildRuntimeEnv(\n appDir: string,\n projectName: string,\n scan: ScanResult,\n provisionEnv: Record<string, string>,\n containerPort: number,\n options?: DeployAppOptions,\n appEnv: Record<string, string> = {},\n s3Engine: 'rustfs' | 'minio' = 'rustfs',\n): RuntimeEnvPlan {\n const sidecar = planSidecars(appDir, projectName, scan, provisionEnv, options, s3Engine)\n const environment = options?.environment ?? appEnv.HAI_DEPLOY_ENVIRONMENT ?? 'prod'\n const nodeEnv = environment === 'dev' || environment === 'development' ? 'development' : environment === 'test' ? 'test' : 'production'\n const env = mergeEnvironmentLayers([{\n NODE_ENV: nodeEnv,\n HOST: '0.0.0.0',\n PORT: String(containerPort),\n HAI_SERV_SERVER_HOST: '0.0.0.0',\n HAI_SERV_SERVER_PORT: String(containerPort),\n }, Object.fromEntries(Object.entries(appEnv).filter(([name]) => !CONTAINER_ENV_KEYS.has(name))), sidecar.env, provisionEnv])\n return { env, sidecar }\n}\n\n/**\n * 生成 compose 文件内容。\n * @param options - 生成参数\n * @param options.projectName - 项目名\n * @param options.imageRef - 应用镜像引用\n * @param options.appVersion - 应用发布版本,例如 1.2.3;不改变持久化卷身份\n * @param options.hostPort - 宿主机映射端口\n * @param options.https - 可选的统一 HTTPS 入口与 Certbot 设置。\n * @param options.containerPort - 容器内端口\n * @param options.primaryService - 主运行服务角色,独立 API 为 serv,浏览器站点为 web。\n * @param options.sidecar - sidecar 规划\n * @param options.web - 同一编排中的 Web 镜像与监听端口,独立于私有应用环境\n * @param options.web.imageRef - Web 镜像引用\n * @param options.web.containerPort - Web 容器监听端口\n * @param options.mountWebConfig - 独立Vite站点是否挂载公开的目录路由配置,默认不挂载。\n * @param options.gateway - SSR/API 自建对象存储的公开 Nginx 入口;只在没有现成 Web 代理时启用。\n * @param options.requestAccessPolicy - 是否为本次更新的后端挂载只读请求策略快照。\n * @param options.nodeRuntime - Node 后端默认重读运行文件;SSR web 显式标识。\n * @param options.nodeOptions - 打包时保留的 Node 启动参数,更新需重新部署。\n * @returns compose YAML 字符串\n * @example 模块内部上下文\n * ```ts\n * const sidecar: SidecarPlan = { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, containerEnv: {}, dependsOn: [], secrets: [] }\n * const yaml = generateComposeFile({ projectName: 'shop', appVersion: '1.0.0', imageRef: 'shop:1.0.0-build1', hostPort: 8080, containerPort: 3000, sidecar })\n * ```\n */\nexport function generateComposeFile(options: {\n projectName: string\n appVersion: string\n imageRef: string\n hostPort: number\n containerPort: number\n /** 独立 API 为 serv,独立静态或 SSR 站点为 web。 */\n primaryService?: 'serv' | 'web'\n sidecar: SidecarPlan\n /** Web 公开入口;私有运行环境仅属于 API 服务。 */\n web?: { imageRef: string, containerPort: number }\n mountWebConfig?: boolean\n gateway?: boolean\n /** 本次更新的服务挂载不可变、已验证的请求策略快照。 */\n requestAccessPolicy?: boolean\n /** Node 后端每次启动重读运行文件;serv 默认开启,SSR web 由扫描结果标识。 */\n nodeRuntime?: boolean\n /** 需要保留的 Node 启动参数;变化仍需重新部署容器。 */\n nodeOptions?: string\n /** HTTPS 与 Certbot 的统一入口设置。 */\n https?: DockerSshProviderConfig['expose']['https']\n}): string {\n const { projectName, imageRef, hostPort, containerPort, sidecar } = options\n const primaryService = options.primaryService ?? 'serv'\n const nodeRuntime = options.nodeRuntime ?? primaryService === 'serv'\n\n const app: ComposeService = {\n image: imageRef,\n labels: { 'org.opencontainers.image.version': options.appVersion },\n container_name: `hai-${projectName}-${primaryService}`,\n restart: 'unless-stopped',\n // 镜像已由 load 注入本地,禁止 compose 再从 registry 拉取\n pull_policy: 'never',\n env_file: ['.env.runtime'],\n ports: [`${hostPort}:${containerPort}`],\n networks: ['hai-app'],\n }\n if (primaryService === 'serv') {\n // 与应用相同的公开 Schema 和环境解析;不传 --input-type,避免预加载时传给日志 worker。\n app.healthcheck = {\n test: ['CMD', 'node', '-e', '(async () => { try { const { core } = await import(\\'@h-ai/core\\'); const { ServConfigSchema } = await import(\\'@h-ai/serv\\'); core.init({ configDir: \\'./config\\' }); const { server, http } = ServConfigSchema.parse(core.config.getOrThrow(\\'serv\\')); if (http.health === false) process.exit(0); const response = await fetch(\\'http://127.0.0.1:\\' + server.port + http.health.path, { signal: AbortSignal.timeout(4000) }); process.exit(response.ok ? 0 : 1); } catch { process.exit(1); } })()'],\n interval: '30s',\n timeout: '5s',\n start_period: '15s',\n retries: 3,\n }\n }\n const appVolumes = [...sidecar.appVolumes]\n const appEnvironment: Record<string, string> = {}\n if (nodeRuntime) {\n delete app.env_file\n appVolumes.push('./.env.runtime:/run/hai/.env.runtime:ro', './middleware.env:/run/hai/middleware.env:ro', './runtime-env.mjs:/run/hai/runtime-env.mjs:ro')\n appEnvironment.NODE_OPTIONS = (`--import /run/hai/runtime-env.mjs${options.nodeOptions ? ` ${options.nodeOptions}` : ''}`).replaceAll('$', () => '$$')\n }\n if (options.requestAccessPolicy)\n appVolumes.push('./request-access.yml:/run/hai/request-access.yml:ro')\n if (options.web || options.gateway)\n appEnvironment.HAI_DEPLOY_PRIVATE_PROXY = '1'\n if (Object.keys(appEnvironment).length)\n app.environment = appEnvironment\n if (options.mountWebConfig)\n appVolumes.push('./web.conf:/etc/nginx/conf.d/default.conf:ro')\n if (appVolumes.length)\n app.volumes = appVolumes\n if (sidecar.dependsOn.length > 0)\n app.depends_on = Object.fromEntries(sidecar.dependsOn.map(name => [name, { condition: sidecar.composeServices[name]?.healthcheck ? 'service_healthy' : 'service_started' }]))\n\n const services: Record<string, ComposeService> = { [primaryService]: app, ...sidecar.composeServices }\n if (options.web) {\n delete app.ports\n services.web = {\n image: options.web.imageRef,\n labels: { 'org.opencontainers.image.version': options.appVersion },\n container_name: `hai-${projectName}-web`,\n restart: 'unless-stopped',\n pull_policy: 'never',\n ports: [`${hostPort}:${options.web.containerPort}`],\n environment: { PUBLIC_API_BASE: '' },\n healthcheck: { test: ['CMD', 'wget', '-Y', 'off', '-q', '-O', '/dev/null', `http://127.0.0.1:${options.web.containerPort}/_hai/web-health`], interval: '30s', timeout: '5s', retries: 3 },\n volumes: ['./web.conf:/etc/nginx/conf.d/default.conf:ro'],\n depends_on: sidecar.services.includes('storage') ? ['serv', 'storage'] : ['serv'],\n networks: ['hai-app'],\n }\n }\n if (options.gateway) {\n delete app.ports\n services.gateway = {\n image: IMAGES.nginx,\n container_name: `hai-${projectName}-gateway`,\n restart: 'unless-stopped',\n ports: [`${hostPort}:8080`],\n healthcheck: { test: ['CMD', 'wget', '-Y', 'off', '-q', '-O', '/dev/null', 'http://127.0.0.1:8080/_hai/gateway-health'], interval: '30s', timeout: '5s', retries: 3 },\n volumes: ['./web.conf:/etc/nginx/conf.d/default.conf:ro'],\n depends_on: [primaryService, ...(sidecar.services.includes('storage') ? ['storage'] : [])],\n networks: ['hai-app'],\n }\n }\n if (options.https) {\n const proxy = services[options.gateway ? 'gateway' : options.web ? 'web' : primaryService]!\n const https = options.https\n const httpPort = options.gateway ? 8080 : options.web?.containerPort ?? containerPort\n proxy.ports = [...proxy.ports as string[], `${https.port}:${httpPort === 8443 ? 8444 : 8443}`]\n const certificates = https.type === 'files' ? './tls' : `../../https/certificates/${https.domain}`\n proxy.volumes = [\n ...proxy.volumes as string[],\n `${certificates}:/etc/nginx/tls:ro`,\n './https-start.sh:/run/hai/https-start.sh:ro',\n ...(https.type === 'letsencrypt' ? ['../../https/webroot:/var/www/certbot:ro'] : []),\n ]\n proxy.entrypoint = ['sh', '/run/hai/https-start.sh']\n if (https.type === 'letsencrypt') {\n services.certbot = {\n image: CERTBOT_IMAGE,\n restart: 'unless-stopped',\n entrypoint: ['sh', '/run/hai/renew-https.sh'],\n volumes: [\n '../../https/acme:/etc/letsencrypt',\n '../../https/webroot:/var/www/certbot',\n `../../https/certificates/${https.domain}:/output`,\n './renew-https.sh:/run/hai/renew-https.sh:ro',\n ],\n networks: ['hai-app'],\n }\n }\n }\n const compose: Record<string, unknown> = {\n 'x-hai-version': options.appVersion,\n services,\n 'networks': {\n 'hai-app': {},\n },\n }\n if (Object.keys(sidecar.volumes).length > 0)\n compose.volumes = sidecar.volumes\n\n for (const service of Object.values(services))\n service.pull_policy = 'never'\n return stringify(compose, { aliasDuplicateObjects: false })\n}\n\n/**\n * 生成同源 Web/API 的 Nginx 配置,保留运行时配置及 SPA 页面刷新。\n * API 上限由 @h-ai/crypto 的同一明文容量推导密文预算;\n * 关闭请求缓冲,让应用在读取过程中执行握手、公钥和正文的更细预算。\n * @param port - API 容器监听端口\n * @param apiPrefix - 应用实际 API 前缀,不允许向 Nginx 配置注入指令\n * @param options - Web 监听端口和双向业务明文 UTF-8 字节上限,缺省使用 crypto 默认值\n * @param options.webPort - Web 容器监听端口,默认 8080。\n * @param options.maxPlaintextBytes - 业务明文 UTF-8 字节上限。\n * @param options.webBasePath - 无末尾斜杠的Web挂载目录,缺省或空字符串为域名根目录。\n * @param options.storageBucket - 自建私有 S3 桶,配置后对象请求由 Nginx 直达 storage。\n * @param options.storageBasePath - 对象入口目录,转发前移除;空字符串保持根桶路径。\n * @param options.trustedEdgeProxies - Nginx 前方显式可信的负载均衡 IP/CIDR,默认不信任上游头。\n * @param options.backendPaths - 后端实际启用的健康、就绪及文档精确路径,认证仍由后端执行。\n * @returns 仅含公开路由的 Nginx 配置\n * @example 模块内部上下文\n * ```ts\n * const nginx = generateWebProxyConfig(3000, '/api', { webPort: 8080 }) // Web 将同源 /api 转发至 serv 服务。\n * ```\n */\nexport function generateWebProxyConfig(port: number, apiPrefix: string, options: { webPort?: number, maxPlaintextBytes?: number, webBasePath?: string, backendPaths?: string[], storageBucket?: string, storageBasePath?: string, trustedEdgeProxies?: string[] } = {}): string {\n const bodyLimits = resolveTransportBodyLimits(options.maxPlaintextBytes)\n const webPort = options.webPort ?? 8080\n const webBasePath = options.webBasePath ?? ''\n const apiPath = apiPrefix.replace(/\\/+$/, '')\n const backendPaths = [...new Set(options.backendPaths ?? ['/health'])]\n if (!/^\\/[\\w/-]+$/.test(apiPrefix) || ![port, webPort].every(value => Number.isInteger(value) && value >= 1 && value <= 65535)\n || backendPaths.some(path => !/^\\/[\\w./-]*$/.test(path) || path.startsWith('//') || path.split('/').some(part => part === '.' || part === '..') || path === `${webBasePath}/runtime-config.js` || path === '/_hai/web-health')\n || (webBasePath && (backendPaths.includes(webBasePath) || webBasePath === apiPath || webBasePath.startsWith(`${apiPath}/`)))) {\n throw new Error('Invalid web proxy target')\n }\n const webLocation = renderWebLocation(webBasePath)\n const storageLocation = options.storageBucket ? renderStorageLocation(options.storageBucket, [apiPath, ...backendPaths, ...(options.storageBasePath ? [`${webBasePath}/_app`, `${webBasePath}/assets`, `${webBasePath}/runtime-config.js`] : [webBasePath])], options.storageBasePath) : ''\n const backendLocations = backendPaths.map(path => ` location = ${path} {\n proxy_pass http://serv:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Real-IP $remote_addr;\n }\n`).join('')\n return `${options.storageBucket ? renderStorageUpstream(options.storageBucket, options.storageBasePath) : ''}server {\n listen ${webPort};\n server_name _;\n${renderTrustedEdgeProxies(options.trustedEdgeProxies)} root /usr/share/nginx/html;\n large_client_header_buffers 4 32k;\n${storageLocation}${webLocation} location = ${webBasePath}/runtime-config.js {\n add_header Cache-Control \"no-store\";\n default_type application/javascript;\n return 200 'globalThis.__HAI_PUBLIC_CONFIG__={apiBase:globalThis.location.origin+\"${apiPrefix}\"};';\n }\n location = /_hai/web-health {\n access_log off;\n return 200 'ok';\n }\n${backendLocations} location ${apiPrefix.replace(/\\/$/, '')}/ {\n client_max_body_size ${bodyLimits.encryptedPayloadBytes};\n proxy_pass http://serv:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_buffer_size 32k;\n proxy_buffers 8 32k;\n }\n}\n`\n}\n\n/**\n * 生成私有对象直连路由;不重写签名所绑定的 Host、原始 URI 和查询,不把大文件送进应用。\n * @param bucket - 自建桶名;仅接受可安全用于 S3 路径与 Nginx location 的 DNS 桶名。\n * @param reservedPaths - 应用目录和 API 前缀,桶路径不能遮蔽其中任一路由。\n * @param storageBasePath - 已校验的公开入口目录,空字符串保持根桶路径。\n * @returns 不含凭据、不记录签名查询的 location 片段。\n * @example 模块内部上下文\n * ```ts\n * const route = renderStorageLocation('uploads', ['/api/v1', '/portal'])\n * void route\n * ```\n */\nfunction renderStorageLocation(bucket: string, reservedPaths: string[], storageBasePath = ''): string {\n // 与网站目录共用安全路径校验;入口可位于网站目录内,但不能覆盖 API、资源或健康接口。\n renderWebLocation(storageBasePath)\n const path = `${storageBasePath}/${bucket}`\n const reserved = ['/health', '/_hai', ...reservedPaths].filter(Boolean)\n if (!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(bucket) || bucket.includes('..')\n || ['health', '_hai'].includes(bucket)\n || reserved.some(item => item === path || item.startsWith(`${path}/`) || path.startsWith(`${item}/`)\n || (storageBasePath && (item === storageBasePath || item.startsWith(`${storageBasePath}/`) || storageBasePath.startsWith(`${item}/`))))) {\n throw new Error('Storage bucket conflicts with application routes or is not a valid DNS bucket name')\n }\n return ` location ^~ ${path}/ {\n # 预签名 URL 属于短期访问凭据,不写入代理访问或错误日志。\n access_log off;\n error_log /dev/null;\n # 对象可能含不可信 HTML;同源下载也不能取得应用脚本权限或泄露签名来源。\n add_header Content-Security-Policy \"sandbox; default-src 'none'; base-uri 'none'; form-action 'none'\" always;\n proxy_hide_header X-Content-Type-Options;\n add_header X-Content-Type-Options nosniff always;\n proxy_hide_header Referrer-Policy;\n add_header Referrer-Policy no-referrer always;\n proxy_hide_header Cache-Control;\n add_header Cache-Control \"private, no-store\" always;\n limit_except GET PUT OPTIONS { deny all; }\n client_max_body_size 0;\n${storageBasePath\n ? ` # map 保留原始 URI 与查询;不在 location 内创建改变代理继承的 if 配置。\n proxy_pass http://hai_storage_proxy$hai_storage_uri;`\n : ' proxy_pass http://storage:9000;'}\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header Connection \"\";\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_connect_timeout 5s;\n proxy_read_timeout 300s;\n proxy_send_timeout 300s;\n }\n`\n}\n\n/**\n * 显式 upstream 允许带原始 URI 变量转发,避免依赖不同容器引擎的运行时 DNS resolver。\n * @param bucket - 已由对象路由校验的自建桶名。\n * @param storageBasePath - 安全入口目录,空字符串无需 URI 映射。\n * @returns 位于 http 上下文的 upstream 与 map,保留编码和查询并移除入口目录。\n * @example 模块内部上下文\n * ```ts\n * const config = renderStorageUpstream('business-files', '/delivery/files')\n * void config\n * ```\n */\nfunction renderStorageUpstream(bucket: string, storageBasePath = ''): string {\n if (!storageBasePath)\n return ''\n const path = `${storageBasePath}/${bucket}`.replaceAll('.', '\\\\\\\\.')\n return `upstream hai_storage_proxy { server storage:9000; }\nmap $request_uri $hai_storage_uri {\n default $request_uri;\n \"~^${path}(/.*)$\" /${bucket}$1;\n}\n`\n}\n\n/**\n * 为独立 API 或 SvelteKit SSR 生成对象存储网关,应用路径(含部署目录)原样转发。\n * @param options - 内部服务、端口、桶、保留路径、transport 容量和上游代理 IP/CIDR。\n * @param options.primaryService - 实际处理请求的应用服务。\n * @param options.port - 应用容器内端口。\n * @param options.bucket - 私有 S3 桶名。\n * @param options.storageBasePath - publicEndpoint 中的代理目录,不包含桶名。\n * @param options.reservedPaths - 不能与桶路由重叠的应用路径。\n * @param options.maxPlaintextBytes - 应用 transport 明文预算。\n * @param options.trustedEdgeProxies - Nginx 上游可信负载均衡 IP/CIDR。\n * @returns 监听 8080 的公开 Nginx 配置,不含应用或对象存储凭据。\n * @example 模块内部上下文\n * ```ts\n * const config = generateApplicationProxyConfig({ primaryService: 'web', port: 3000, bucket: 'uploads', reservedPaths: ['/portal'] })\n * void config\n * ```\n */\nexport function generateApplicationProxyConfig(options: { primaryService: 'serv' | 'web', port: number, bucket?: string, reservedPaths: string[], storageBasePath?: string, maxPlaintextBytes?: number, trustedEdgeProxies?: string[] }): string {\n const { primaryService, port, bucket, reservedPaths, maxPlaintextBytes } = options\n if (!Number.isInteger(port) || port < 1 || port > 65535)\n throw new Error('Invalid application proxy target')\n const bodyLimits = resolveTransportBodyLimits(maxPlaintextBytes)\n return `${bucket ? renderStorageUpstream(bucket, options.storageBasePath) : ''}server {\n listen 8080;\n server_name _;\n${renderTrustedEdgeProxies(options.trustedEdgeProxies)} large_client_header_buffers 4 32k;\n${bucket ? renderStorageLocation(bucket, reservedPaths, options.storageBasePath) : ''} location = /_hai/gateway-health {\n access_log off;\n return 200 'ok';\n }\n location / {\n client_max_body_size ${bodyLimits.encryptedPayloadBytes};\n proxy_pass http://${primaryService}:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header Connection \"\";\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_buffer_size 32k;\n proxy_buffers 8 32k;\n }\n}\n`\n}\n\n/** 上游 LB 只接受显式 IP/CIDR;随后用 Nginx 已验证的 remote_addr 重写转发头。 */\nfunction renderTrustedEdgeProxies(entries: string[] = []): string {\n if (!TrustedProxiesSchema.safeParse(entries).success)\n throw new Error('Invalid trusted edge proxy address')\n if (!entries.length)\n return ''\n return `${entries.map(entry => ` set_real_ip_from ${entry};`).join('\\n')}\\n real_ip_header X-Forwarded-For;\\n real_ip_recursive on;\\n`\n}\n\n/**\n * 目录路由共享同一校验与静态回退;文件命中后直接输出,避免重定向到域名根目录。\n * @param webBasePath - 无末尾斜杠的目录,空字符串为根目录。\n * @returns 包含目录校验、无末尾斜杠跳转和静态回退的 location 配置。\n * @example 模块内部上下文\n * ```ts\n * const locations = renderWebLocation('/portal')\n * void locations\n * ```\n */\nfunction renderWebLocation(webBasePath: string): string {\n if (webBasePath && (!/^\\/[\\w.-]+(?:\\/[\\w.-]+)*$/.test(webBasePath) || webBasePath.split('/').some(segment => segment === '.' || segment === '..') || ['/health', '/_hai/web-health'].includes(webBasePath)))\n throw new Error('Invalid web base path')\n return webBasePath\n ? ` absolute_redirect off;\n location = ${webBasePath} {\n return 308 ${webBasePath}/$is_args$args;\n }\n location ${webBasePath}/ {\n rewrite ^${webBasePath.replaceAll('.', '\\\\.').replaceAll('-', '\\\\-')}/(.*)$ /$1 break;\n try_files $uri/index.html $uri /index.html =404;\n }\n location / { return 404; }\n`\n : ` location / {\n try_files $uri $uri/ /index.html;\n }\n`\n}\n\n/**\n * 独立Vite站点复用目录路由,公开运行配置仍由已有启动脚本生成,保留外部API地址与品牌字段。\n * @param port - Web容器实际监听端口。\n * @param webBasePath - 已声明的Web挂载目录;无末尾斜杠,空字符串表示根目录。\n * @returns 只含静态页面、公开运行配置和健康入口的Nginx配置。\n * @example 模块内部上下文\n * ```ts\n * const config = generateStaticWebConfig(8080, '/portal')\n * void config\n * ```\n */\nexport function generateStaticWebConfig(port: number, webBasePath: string): string {\n if (!Number.isInteger(port) || port < 1 || port > 65535)\n throw new Error('Invalid web proxy target')\n return `server {\n listen ${port};\n server_name _;\n root /usr/share/nginx/html;\n${renderWebLocation(webBasePath)} location = ${webBasePath}/runtime-config.js {\n alias /tmp/hai-runtime-config/runtime-config.js;\n add_header Cache-Control \"no-store\";\n default_type application/javascript;\n }\n location = /health {\n access_log off;\n return 200 'ok';\n }\n}\n`\n}\n\n/**\n * 将环境变量对象序列化为 .env.runtime 内容(每行 KEY=VALUE)。\n * 编码 dotenv 值,不进行脱敏;含密钥时只能写入受保护的运行环境文件。\n * @param env - 要序列化的运行变量,可能包含秘密。\n * @returns 保留字面量值且正确转义的 dotenv 文本,不进行脱敏。\n * @example 模块内部上下文\n * ```ts\n * const content = serializeEnvFile({ NODE_ENV: 'production', HAI_CORE_NAME: 'Shop app' })\n * ```\n */\nexport function serializeEnvFile(env: Record<string, string>): string {\n return `${Object.entries(env)\n .map(([key, value]) => {\n let literal = value\n if (/[\\s#$'\"]/.test(value)) {\n if (value.startsWith('{') || value.startsWith('['))\n literal = `'${value.replaceAll('\\'', '\\\\u0027')}'`\n else if (!value.includes('\\''))\n literal = `'${value}'`\n else\n literal = JSON.stringify(value).replaceAll('$', '$$')\n }\n return `${key}=${literal}`\n })\n .join('\\n')}\\n`\n}\n","/**\n * @h-ai/deploy — docker-ssh 部署 Provider\n *\n * 基于 OCI 镜像 + Docker Compose + SSH 的通用主机部署:消费已有镜像 → tar 打包 → SSH 传输 →\n * 远程 load → compose up → HTTP 健康检查。远程需 SSH、Linux flock/基础工具及 docker/podman + compose。\n * @module deploy-provider-docker-ssh\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n ContainerDeployContext,\n ContainerDeployProvider,\n ContainerRuntime,\n} from '../container/deploy-container-types.js'\nimport type { DeployConfig, DockerSshProviderConfig } from '../deploy-config.js'\nimport type { DeployResult } from '../deploy-types.js'\nimport { createHash, randomBytes } from 'node:crypto'\nimport { chmodSync, existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { request as requestHttps } from 'node:https'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { rootCertificates } from 'node:tls'\nimport { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'\nimport { core, CoreConfigSchema, err, ok, RequestAccessConfigSchema } from '@h-ai/core'\nimport { createTransportBodyPolicy, parseTransportServerKeyRing, resolveTransportBodyLimits } from '@h-ai/crypto'\nimport { stringify } from 'yaml'\nimport { z } from 'zod'\nimport { createDeploymentBundle } from '../container/deploy-bundle.js'\nimport { maskSecrets } from '../container/deploy-command.js'\nimport {\n buildRuntimeEnv,\n generateApplicationProxyConfig,\n generateComposeFile,\n generateStaticWebConfig,\n generateWebProxyConfig,\n serializeEnvFile,\n} from '../container/deploy-container-compose.js'\nimport { createHttpsAssets, renderHttpsProxy } from '../container/deploy-https.js'\nimport { shellArgument } from '../container/deploy-scripts.js'\nimport { createSshExecutor } from '../container/deploy-ssh.js'\nimport { loadDeploymentConfig, loadDeploymentEnvironment, saveDeploymentEnvironment } from '../deploy-environment.js'\nimport { resolveProjectDirectory } from '../deploy-functions.js'\nimport { deployM } from '../deploy-i18n.js'\nimport { getDeployCommandState } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provider-docker-ssh' })\n\n/** 健康检查轮询间隔(毫秒) */\nconst HEALTH_POLL_INTERVAL = 3000\n\n/** 只处理本次选中的应用配置;文件按应用目录读取,运行期路径不回写调用方环境。 */\nfunction prepareRequestAccess(options: { settings: Record<string, unknown>, module: 'serv' | 'kit', directory: string }): HaiResult<{ settings: Record<string, unknown>, snapshot?: string }> {\n const scope = options.module === 'serv' ? options.settings.http : options.settings\n if (!scope || typeof scope !== 'object' || !('access' in scope))\n return ok({ settings: options.settings })\n const configured = RequestAccessConfigSchema.safeParse(scope.access)\n if (!configured.success)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_requestAccessInvalid', { params: { field: options.module === 'serv' ? 'serv.http.access' : 'kit.access' } }))\n try {\n const policy = core.access.loadPolicy(configured.data, options.directory)\n const check = core.access.createRequestCheck(policy)\n if (check.requiresEncryption && !options.settings.transport)\n throw new Error('Transport encryption is required but not configured')\n if (configured.data === false || !('file' in configured.data))\n return ok({ settings: options.settings })\n const access = { file: '/run/hai/request-access.yml' }\n const settings = options.module === 'serv'\n ? { ...options.settings, http: { ...scope, access } }\n : { ...options.settings, access }\n return ok({ settings, snapshot: stringify(policy, { aliasDuplicateObjects: false }) })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_requestAccessInvalid', { params: { field: options.module === 'serv' ? 'serv.http.access' : 'kit.access' } }))\n }\n}\n\n/** 健康检查最大轮询次数 */\nconst HEALTH_MAX_ATTEMPTS = 40\n\n/** 只提取 Serv 已注册的精确路径;阻止配置路径进入 Nginx 指令或 shell 语法。 */\nfunction servicePath(value: unknown, fallback: string): string {\n const path = value ?? fallback\n if (typeof path !== 'string' || !/^\\/[\\w./-]*$/.test(path) || path.startsWith('//') || path.split('/').some(part => part === '.' || part === '..'))\n throw new Error('Invalid service endpoint path')\n return path\n}\n\n/** 未配置的健康检查沿用 Serv 默认;文档必须显式使用对象启用。 */\nfunction endpointSettings(value: unknown): Record<string, unknown> {\n if (value === undefined)\n return {}\n if (!value || typeof value !== 'object' || Array.isArray(value))\n throw new Error('Invalid service endpoint configuration')\n return value as Record<string, unknown>\n}\n\n/** 只接收服务器脚本原子发布的终态;匹配 ID 后才能确认本次执行完成。 */\nconst ServerResultSchema = z.object({\n deploymentId: z.string(),\n stage: z.enum(['preflight', 'credentials', 'recover', 'images', 'dependencies', 'start', 'https', 'health', 'complete']),\n exitCode: z.number().int().min(0).max(255),\n durationSeconds: z.number().int().nonnegative(),\n recoveryStatus: z.enum(['not-needed', 'passed', 'failed', 'stopped']).optional(),\n})\n\n/** 生成不可变部署 ID:`YYYYMMDD-HHmmss-<random>`。 */\nfunction makeDeploymentId(): string {\n const now = new Date()\n const pad = (n: number): string => String(n).padStart(2, '0')\n const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`\n + `-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`\n return `${stamp}-${randomBytes(3).toString('hex')}`\n}\n\n/** 睡眠指定毫秒。 */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/**\n * 创建 docker-ssh 部署 Provider。\n * @param config - docker-ssh Provider 配置\n * @param container - Compose 中间件参数\n * @returns 容器部署 Provider 实例\n * @example 模块内部上下文\n * ```ts\n * const provider = createDockerSshProvider({ type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } })\n * const name = provider.name // 创建本身不连接 SSH;在线发布仍需有效 SSH 配置。\n * ```\n */\nexport function createDockerSshProvider(\n config: DockerSshProviderConfig,\n container?: DeployConfig['container'],\n): ContainerDeployProvider {\n const ssh = config.ssh ? createSshExecutor(config.ssh) : undefined\n const baseDir = config.remote.baseDir\n\n /** 探测远程容器运行时与 compose 可用性。 */\n async function detectRemoteRuntime(): Promise<HaiResult<ContainerRuntime>> {\n if (!ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n const candidates: ContainerRuntime[] = config.remote.runtime === 'auto'\n ? ['podman', 'docker']\n : [config.remote.runtime]\n\n for (const runtime of candidates) {\n const versionResult = await ssh.exec(`${runtime} version`, { timeoutMs: 20_000 })\n if (!versionResult.success)\n continue\n const composeResult = await ssh.exec(`${runtime} compose version`, { timeoutMs: 20_000 })\n if (composeResult.success) {\n logger.info('Remote container runtime detected', { runtime })\n return ok(runtime)\n }\n }\n return err(\n HaiDeployError.REMOTE_COMMAND_FAILED,\n deployM('deploy_remoteRuntimeMissing', { params: { runtime: candidates.join(' / ') } }),\n )\n }\n\n /** HTTP 健康检查:轮询访问地址直到返回成功。 */\n async function healthCheck(url: string, certificate?: string): Promise<boolean> {\n for (let attempt = 0; attempt < HEALTH_MAX_ATTEMPTS; attempt++) {\n try {\n if (certificate) {\n const healthy = await new Promise<boolean>((resolve) => {\n const request = requestHttps(url, { ca: [...rootCertificates, certificate], timeout: 5000 }, (response) => {\n response.resume()\n resolve(response.statusCode !== undefined && response.statusCode >= 200 && response.statusCode < 300)\n })\n request.on('error', () => resolve(false))\n request.on('close', () => resolve(false))\n request.on('timeout', () => request.destroy())\n request.end()\n })\n if (healthy)\n return true\n }\n else {\n const response = await fetch(url, { signal: AbortSignal.timeout(5000) })\n // 健康检查只消费状态码,主动释放响应体和连接,避免失败轮询积压未读数据。\n await response.body?.cancel()\n if (response.ok)\n return true\n }\n }\n catch {\n // 未就绪,继续轮询\n }\n await sleep(HEALTH_POLL_INTERVAL)\n }\n return false\n }\n\n const deploy = async (context: ContainerDeployContext): Promise<HaiResult<DeployResult>> => {\n const { appDir, projectName, scan, provisionEnv, appEnv, options } = context\n const deploymentId = makeDeploymentId()\n const hostPort = config.expose.hostPort\n const https = config.expose.https\n const httpsAssets = https ? createHttpsAssets(https, resolveProjectDirectory(appDir)) : undefined\n const deploymentRoot = join(resolveProjectDirectory(appDir), '.hai', 'deploy', options?.environment ?? 'prod')\n const artifact = context.artifact\n const resolvedBuildDir = context.artifactDir\n const images = artifact.images\n const web = images.find(image => image.name === 'web')\n const primaryService = artifact.primaryService\n const app = images.find(image => image.name === primaryService)\n if (options?.selectedServices) {\n const available: string[] = [...images.map(image => image.name), ...scan.requiredServices]\n const invalid = options.selectedServices.find(name => !available.includes(name))\n if (!options.selectedServices.length || new Set(options.selectedServices).size !== options.selectedServices.length || invalid)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: invalid ?? options.selectedServices.join(', ') } }))\n }\n const hasWebProxy = primaryService === 'serv' && artifact.hasWeb\n const partial = artifact.partial || options?.selectedServices !== undefined\n const containerPort = app?.containerPort ?? (primaryService === 'serv' ? artifact.servContainerPort : artifact.webContainerPort) ?? config.expose.containerPort\n const webContainerPort = web?.containerPort ?? artifact.webContainerPort ?? 8080\n const host = config.ssh?.host\n const url = https ? `https://${https.domain}${https.port === 443 ? '' : `:${https.port}`}` : host ? `http://${host.includes(':') ? `[${host}]` : host}:${hostPort}` : `http://SERVER_HOST:${hostPort}`\n const webBasePath = artifact.webBasePath ?? ''\n const applicationUrl = `${url}${webBasePath ? `${webBasePath}/` : ''}`\n const standaloneWebConfig = primaryService === 'web' && !scan.isSvelteKit && (!!webBasePath || !!https)\n const healthPaths = hasWebProxy ? ['/_hai/web-health', `${webBasePath}/`] : scan.isSvelteKit ? [`${webBasePath}/`] : primaryService === 'serv' ? [] : standaloneWebConfig ? ['/health', `${webBasePath}/`] : ['/health']\n\n // 先保存开通结果和 sidecar 凭据,传输失败后仍可检查与复用配置。\n const { env, sidecar } = buildRuntimeEnv(appDir, projectName, scan, provisionEnv, containerPort, options, appEnv, container?.s3Engine)\n if (https && scan.isSvelteKit && !env.ORIGIN)\n env.ORIGIN = url\n const managedStorage = sidecar.services.includes('storage') ? JSON.parse(sidecar.env.HAI_STORAGE) as { bucket: string, secretAccessKey: string, publicEndpoint?: unknown } : undefined\n let storageBasePath = ''\n if (managedStorage?.publicEndpoint !== undefined) {\n // 与 Storage 的公开端点约束一致,在归档/上传前报告错误,不输出配置中的 URL 或秘密。\n try {\n if (typeof managedStorage.publicEndpoint !== 'string')\n throw new Error('Invalid public endpoint type')\n // eslint-disable-next-line no-control-regex -- 在 URL 标准化前拒绝控制字符及编码目录。\n const unsafeCharacters = /[\\u0000-\\u0020\\u007F\\\\%]/.test(managedStorage.publicEndpoint)\n const endpoint = new URL(managedStorage.publicEndpoint)\n if (!['http:', 'https:'].includes(endpoint.protocol) || endpoint.username || endpoint.password || endpoint.search || endpoint.hash\n || !/^\\/(?:[\\w.-]+(?:\\/[\\w.-]+)*\\/?)?$/.test(endpoint.pathname)\n || unsafeCharacters || /(?:^|\\/)\\.{1,2}(?:\\/|$)/.test(managedStorage.publicEndpoint)) {\n throw new Error('Invalid public endpoint origin')\n }\n storageBasePath = endpoint.pathname.replace(/\\/+$/, '')\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storagePublicEndpointInvalid'))\n }\n }\n // 应用增量继承已安装连接配置;对外地址或桶等配置改变须全量切换,不能静默沿用旧值。\n const storageRouting = managedStorage ? createHash('sha256').update(JSON.stringify({ ...managedStorage, secretAccessKey: undefined })).digest('hex') : ''\n // SSR/API 没有现成 Web Nginx 时追加网关;静态客户端不能持有存储服务端凭据。\n const gateway = !hasWebProxy && (!!managedStorage || (!!https && !standaloneWebConfig))\n if (gateway && primaryService === 'web' && !scan.isSvelteKit)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageBackendRequired'))\n const proxyService = gateway ? 'gateway' : 'web'\n if (gateway)\n healthPaths.push('/_hai/gateway-health')\n const updatesApp = options?.selectedServices ? options.selectedServices.includes(primaryService) : !!app\n const serverPath = join(appDir, 'config', '_serv.yml')\n const server = existsSync(serverPath) || hasWebProxy ? loadDeploymentConfig('serv', serverPath, env) : ok<Record<string, unknown>>({})\n if (!server.success)\n return server\n const backendPaths: string[] = []\n try {\n const http = endpointSettings(server.data.http)\n if (primaryService === 'serv' && http.health !== false) {\n const health = endpointSettings(http.health)\n const path = servicePath(health.path, '/health')\n healthPaths.unshift(path)\n backendPaths.push(path, servicePath(health.readyPath, '/ready'))\n }\n if (hasWebProxy) {\n // 生成应用按 Core 环境关闭生产文档,不能用部署目标名或 NODE_ENV 猜测启用状态。\n const corePath = join(appDir, 'config', '_core.yml')\n const settings = existsSync(corePath) ? loadDeploymentConfig('core', corePath, env) : ok(env.HAI_CORE ? JSON.parse(env.HAI_CORE) : { env: env.HAI_CORE_ENV })\n if (!settings.success)\n return settings\n const application = CoreConfigSchema.safeParse(settings.data)\n if (!application.success)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n if (application.data.env !== 'production') {\n if (http.openapi !== undefined && http.openapi !== false)\n backendPaths.push(servicePath(endpointSettings(http.openapi).path, '/openapi.json'))\n if (http.docs !== undefined && http.docs !== false) {\n const docsPath = servicePath(endpointSettings(http.docs).path, '/docs')\n backendPaths.push(docsPath, `${docsPath.slice(0, docsPath.lastIndexOf('/') + 1)}_hai/scalar.js`)\n }\n }\n }\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n }\n let requestAccessSnapshot: string | undefined\n if (updatesApp && primaryService === 'serv') {\n const prepared = prepareRequestAccess({ settings: server.data, module: 'serv', directory: appDir })\n if (!prepared.success)\n return prepared\n Object.assign(server.data, prepared.data.settings)\n requestAccessSnapshot = prepared.data.snapshot\n if (requestAccessSnapshot)\n env.HAI_SERV = JSON.stringify(server.data)\n }\n let feedbackTransportBytes: number | undefined\n if (scan.haiModules?.includes('@h-ai/feedback')) {\n const policy = loadDeploymentConfig('feedback', join(appDir, 'config', '_feedback.yml'), env)\n if (!policy.success)\n return policy\n try {\n feedbackTransportBytes = resolveFeedbackBudget(policy.data).maxTransportBytes\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_transportBodyLimitInvalid'))\n }\n }\n let protectedTransport = !!server.data.transport\n let applicationPlaintextBytes: number | undefined\n if (scan.isSvelteKit) {\n const kitPath = join(appDir, 'config', '_kit.yml')\n const kit = existsSync(kitPath) ? loadDeploymentConfig('kit', kitPath, env) : ok({})\n if (!kit.success)\n return kit\n if (updatesApp) {\n const prepared = prepareRequestAccess({ settings: kit.data, module: 'kit', directory: appDir })\n if (!prepared.success)\n return prepared\n Object.assign(kit.data, prepared.data.settings)\n requestAccessSnapshot = prepared.data.snapshot\n if (requestAccessSnapshot)\n env.HAI_KIT = JSON.stringify(kit.data)\n }\n const transport = (kit.data as Record<string, unknown>).transport\n if (transport && typeof transport === 'object') {\n protectedTransport = !('enabled' in transport) || transport.enabled !== false\n try {\n const configured = (transport as { maxPlaintextBytes?: number | 'auto' }).maxPlaintextBytes\n const routes = (transport as { routePlaintextBytes?: Record<string, number> }).routePlaintextBytes\n const limits = resolveTransportBodyLimits(Math.max(createTransportBodyPolicy(configured === 'auto' ? undefined : configured, routes).maximum.plaintextBytes, feedbackTransportBytes ?? 0))\n // adapter-node 默认容量比 transport 小;正式部署必须使用同一派生密文预算。\n env.BODY_SIZE_LIMIT = String(limits.encryptedPayloadBytes)\n applicationPlaintextBytes = limits.plaintextBytes\n }\n catch (error) {\n return err(HaiDeployError.CONFIG_ERROR, error instanceof RangeError ? error.message : deployM('deploy_transportBodyLimitInvalid'))\n }\n }\n }\n if (updatesApp && protectedTransport && scan.haiModules?.includes('@h-ai/crypto') && !parseTransportServerKeyRing(env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING).success)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_transportKeyRingInvalid', { params: { path: join(scan.envDir ?? appDir, `.env.${options?.environment ?? 'prod'}.local`) } }))\n let webProxy: string | undefined\n if (hasWebProxy) {\n // 路由取当前服务的真实配置,不扫描相邻应用或猜测 fullstack 布局。\n const http = server.data.http as { apiPrefix?: string } | undefined\n const cors = server.data.cors as { origin?: string } | undefined\n const apiPrefix = http?.apiPrefix ?? '/api/v1'\n if (typeof apiPrefix !== 'string' || !/^\\/[\\w/-]+$/.test(apiPrefix)) {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n }\n if (webBasePath && ([...backendPaths, '/_hai/web-health'].includes(webBasePath) || webBasePath === apiPrefix.replace(/\\/+$/, '') || webBasePath.startsWith(`${apiPrefix.replace(/\\/+$/, '')}/`)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webBaseConflict'))\n const transport = server.data.transport as { maxPlaintextBytes?: number | 'auto', routePlaintextBytes?: Record<string, number> } | false | undefined\n try {\n const configured = transport ? transport.maxPlaintextBytes : undefined\n const limits = resolveTransportBodyLimits(Math.max(createTransportBodyPolicy(configured === 'auto' ? undefined : configured, transport ? transport.routePlaintextBytes : undefined).maximum.plaintextBytes, feedbackTransportBytes ?? 0))\n webProxy = generateWebProxyConfig(containerPort, apiPrefix, { webPort: webContainerPort, maxPlaintextBytes: limits.plaintextBytes, webBasePath, backendPaths, storageBucket: managedStorage?.bucket, storageBasePath, trustedEdgeProxies: config.trustedEdgeProxies })\n }\n catch (error) {\n return err(HaiDeployError.CONFIG_ERROR, error instanceof RangeError ? error.message : deployM(managedStorage ? 'deploy_storageProxyInvalid' : 'deploy_transportBodyLimitInvalid'))\n }\n // 每次从当前配置生成,避免上次运行环境里的父对象遮蔽新修改;保留明确 Origin。\n env.HAI_SERV = JSON.stringify({ ...server.data, cors: { ...cors, origin: (!cors?.origin || cors.origin === '*') && (config.ssh || https) ? url : cors?.origin ?? '*' } })\n }\n else if (gateway) {\n try {\n const http = server.data.http as { apiPrefix?: string } | undefined\n if (primaryService === 'serv') {\n const transport = server.data.transport as { maxPlaintextBytes?: number | 'auto', routePlaintextBytes?: Record<string, number> } | undefined\n applicationPlaintextBytes = Math.max(createTransportBodyPolicy(transport?.maxPlaintextBytes === 'auto' ? undefined : transport?.maxPlaintextBytes, transport?.routePlaintextBytes).maximum.plaintextBytes, feedbackTransportBytes ?? 0)\n }\n webProxy = generateApplicationProxyConfig({ primaryService, port: containerPort, bucket: managedStorage?.bucket, storageBasePath, reservedPaths: [http?.apiPrefix ?? '/api/v1', ...(storageBasePath ? [`${webBasePath}/_app`, `${webBasePath}/assets`, `${webBasePath}/runtime-config.js`] : [webBasePath])], maxPlaintextBytes: applicationPlaintextBytes, trustedEdgeProxies: config.trustedEdgeProxies })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageProxyInvalid'))\n }\n }\n else if (standaloneWebConfig) {\n if (['/health', '/_hai/web-health'].includes(webBasePath))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webBaseConflict'))\n webProxy = generateStaticWebConfig(containerPort, webBasePath)\n }\n if (https && webProxy)\n webProxy = renderHttpsProxy(webProxy, https, hasWebProxy ? webContainerPort : gateway ? 8080 : containerPort)\n if (https && primaryService === 'serv' && !hasWebProxy) {\n const cors = server.data.cors as { origin?: string } | undefined\n env.HAI_SERV = JSON.stringify({ ...server.data, cors: { ...cors, origin: !cors?.origin || cors.origin === '*' ? url : cors.origin } })\n }\n // 一次交付对应一个目录;自定义同名输出也不覆盖已经可复制的旧包。\n const requestedOutput = options?.output ?? join(deploymentRoot, `bundle-${projectName}-${deploymentId}-${artifact.appVersion}.tar.gz`)\n const compressed = requestedOutput.endsWith('.tar.gz')\n const stem = basename(requestedOutput).replace(/\\.tar(?:\\.gz)?$/i, '')\n const suffix = `-${artifact.appVersion}`\n const name = stem.endsWith(suffix) ? stem : `${stem}${suffix}`\n if (!/^[\\w.+-]+$/.test(name))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleNameInvalid'))\n const artifactDir = resolve(dirname(requestedOutput), name)\n if (existsSync(artifactDir))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleDirectoryExists', { params: { path: artifactDir } }))\n mkdirSync(dirname(artifactDir), { recursive: true, mode: 0o700 })\n mkdirSync(artifactDir, { mode: 0o700 })\n chmodSync(artifactDir, 0o700)\n const envPath = join(artifactDir, '.env.runtime')\n writeFileSync(envPath, serializeEnvFile(env), { mode: 0o600 })\n if (requestAccessSnapshot)\n writeFileSync(join(artifactDir, 'request-access.yml'), requestAccessSnapshot, { mode: 0o600 })\n writeFileSync(join(artifactDir, 'middleware-runtime.env'), serializeEnvFile(sidecar.containerEnv), { mode: 0o600 })\n if (options?.environment) {\n const environment = loadDeploymentEnvironment({ environment: options.environment, envDir: options.envDir ?? scan.envDir ?? appDir })\n if (!environment.success)\n return environment\n const saved = saveDeploymentEnvironment(environment.data, { HAI_DEPLOY_ENVIRONMENT: environment.data.environment, HAI_CORE_ENV: environment.data.values.HAI_CORE_ENV, ...sidecar.env, ...provisionEnv })\n if (!saved.success)\n return saved\n }\n\n const composeName = `docker-compose-${artifact.appVersion}.yml`\n const composeContent = generateComposeFile({\n projectName,\n appVersion: artifact.appVersion,\n imageRef: app?.imageRef ?? 'localhost/hai-unselected:0',\n hostPort,\n containerPort,\n primaryService,\n requestAccessPolicy: requestAccessSnapshot !== undefined,\n nodeRuntime: primaryService === 'serv' || scan.isSvelteKit,\n nodeOptions: env.NODE_OPTIONS,\n sidecar,\n web: hasWebProxy ? { imageRef: web?.imageRef ?? 'localhost/hai-unselected:0', containerPort: webContainerPort } : undefined,\n mountWebConfig: standaloneWebConfig,\n gateway,\n https,\n })\n const composePath = join(artifactDir, composeName)\n writeFileSync(composePath, composeContent)\n if (webProxy)\n writeFileSync(join(artifactDir, 'web.conf'), webProxy)\n const selected = options?.selectedServices ? [...options.selectedServices] : artifact.partial ? images.map(image => image.name) : [...images.map(image => image.name), ...Object.keys(sidecar.composeServices)]\n if (gateway && !partial)\n selected.push('gateway')\n if (https?.type === 'letsencrypt' && !partial)\n selected.push('certbot')\n if (!selected.length || selected.some(name => !/^[a-z][a-z0-9-]*$/.test(name)) || new Set(selected).size !== selected.length)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: selected.join(', ') } }))\n for (const name of selected) {\n if (['serv', 'web'].includes(name) && !images.some(image => image.name === name))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: name } }))\n }\n options?.onProgress?.('packaging')\n const bundle = await createDeploymentBundle({\n directory: artifactDir,\n artifactDir: resolvedBuildDir,\n artifact,\n projectName,\n environment: options?.environment ?? 'prod',\n deploymentId,\n config,\n runtime: options?.runtime ?? 'auto',\n selected,\n partial,\n hasWebConfig: !!webProxy,\n proxyService,\n storageRouting,\n containerPort,\n middlewareEnv: serializeEnvFile(sidecar.env),\n healthPaths,\n httpsAssets,\n output: join(artifactDir, `${name}.tar${compressed ? '.gz' : ''}`),\n cacheDirectory: join(resolveProjectDirectory(appDir), '.hai', 'cache', 'images'),\n })\n if (options?.bundleOnly)\n return ok({ url: '', deploymentId, status: 'packaged', provider: 'docker-ssh', healthCheck: 'skipped', envVarsSet: Object.keys(env), ...bundle })\n if (!ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n const ping = await ssh.ping()\n if (!ping.success)\n return ping\n const remoteRuntime = await detectRemoteRuntime()\n if (!remoteRuntime.success)\n return remoteRuntime\n const remoteDir = `${baseDir}/${projectName}`\n const remoteTar = `${remoteDir}/incoming/${basename(bundle.bundlePath)}`\n const prepared = await ssh.exec(`mkdir -p -- ${shellArgument(`${remoteDir}/incoming`)} && chmod 700 -- ${shellArgument(remoteDir)} ${shellArgument(`${remoteDir}/incoming`)}`)\n if (!prepared.success)\n return prepared\n const uploaded = await ssh.upload(bundle.bundlePath, remoteTar)\n if (!uploaded.success)\n return uploaded\n let pendingOutput = ''\n const started = await ssh.exec(\n `mkdir -p ${shellArgument(`${remoteTar}.contents`)} && chmod 600 ${shellArgument(remoteTar)} && tar -xf ${shellArgument(remoteTar)} -C ${shellArgument(`${remoteTar}.contents`)} && sh ${shellArgument(`${remoteTar}.contents/${bundle.startName}`)} ${shellArgument(remoteDir)} && { rm -rf -- ${shellArgument(`${remoteTar}.contents`)} && rm -f -- ${shellArgument(remoteTar)} || printf '[WARN] Deployment passed; incoming archive cleanup failed\\\\n' >&2; }`,\n { timeoutMs: 600_000, secrets: sidecar.secrets, onOutput: (output) => {\n const parts = output.split('\\n')\n for (let index = 0; index < parts.length; index++) {\n // 进度仅解析行首标签,不保留无限长的构建日志行。\n pendingOutput += parts[index]!.slice(0, 512 - pendingOutput.length)\n if (index === parts.length - 1)\n break\n const line = pendingOutput\n pendingOutput = ''\n const stage = /^\\[(preflight|images|dependencies|start|https|health|complete)\\]/.exec(line)?.[1]\n if (stage)\n options?.onProgress?.(stage as 'preflight' | 'images' | 'dependencies' | 'start' | 'https' | 'health' | 'complete')\n }\n } },\n )\n if (!started.success) {\n const resultFile = `${remoteDir}/result-${deploymentId}.json`\n const state = getDeployCommandState(started.error)\n // 独立连接只读核对,绝不因超时自动再运行 apply 或无条件恢复容器。\n const checked = await ssh.exec(`if [ -f ${shellArgument(resultFile)} ]; then cat -- ${shellArgument(resultFile)}; fi`, { timeoutMs: 20_000, maxCaptureChars: 8192 })\n let terminal: z.infer<typeof ServerResultSchema> | undefined\n if (checked.success && !checked.data.stdoutTruncated) {\n try {\n const parsed = ServerResultSchema.safeParse(JSON.parse(checked.data.stdout))\n if (parsed.success && parsed.data.deploymentId === deploymentId)\n terminal = parsed.data\n }\n catch {\n // 缺失、损坏、超限或不匹配的记录都不能证明远端已停止。\n }\n }\n return err({ ...started.error, message: `${started.error.message}\\n${terminal ? deployM('deploy_remoteFinished', { params: { stage: terminal.stage, code: String(terminal.exitCode) } }) : deployM('deploy_remoteUnknown')}`, suggestion: terminal ? deployM('deploy_remoteFinished', { params: { stage: terminal.stage, code: String(terminal.exitCode) } }) : deployM('deploy_remoteUnknown'), ext: { ...started.error.ext, commandExecution: {\n ...state,\n reason: state?.reason ?? 'exit',\n localTermination: state?.localTermination ?? 'unknown',\n remoteExecution: terminal ? 'finished' : 'unknown',\n deploymentId,\n resultFile,\n ...(terminal ? { remoteExitCode: terminal.exitCode, remoteStage: terminal.stage, remoteRecovery: terminal.recoveryStatus } : {}),\n } } })\n }\n\n // 在线部署完成后检查实际公开入口。\n logger.info('Running health check', { url: applicationUrl })\n let healthy = true\n for (const healthPath of healthPaths) {\n if (!await healthCheck(`${url}${healthPath}`, httpsAssets?.['tls/fullchain.pem'])) {\n healthy = false\n break\n }\n }\n if (!healthy) {\n return err(\n { ...HaiDeployError.HEALTH_CHECK_FAILED, message: deployM('deploy_healthCheckFailed', { params: { url: applicationUrl } }), ext: { commandExecution: {\n reason: 'exit',\n localTermination: 'confirmed',\n remoteExecution: 'finished',\n deploymentId,\n resultFile: `${remoteDir}/result-${deploymentId}.json`,\n remoteExitCode: 0,\n remoteStage: 'complete',\n remoteRecovery: 'not-needed',\n } } },\n )\n }\n\n const result: DeployResult = {\n url: applicationUrl,\n deploymentId,\n status: 'ready',\n provider: 'docker-ssh',\n healthCheck: 'passed',\n envVarsSet: Object.keys(env),\n bundlePath: bundle.bundlePath,\n }\n logger.info('docker-ssh deployment complete', { url: applicationUrl, deploymentId })\n return ok(result)\n }\n\n const deploySafely: ContainerDeployProvider['deploy'] = async (context) => {\n try {\n return await deploy(context)\n }\n catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n let safeReason = 'Deployment bundle failed'\n try {\n safeReason = maskSecrets(reason, [...Object.values(context.appEnv ?? {}), config.ssh?.password ?? ''].filter(Boolean))\n }\n catch {\n // 脱敏配置无效时保留固定诊断,不重新暴露原异常。\n }\n logger.error('Deployment bundle failed', { reason: safeReason })\n return err(HaiDeployError.DEPLOY_FAILED, deployM('deploy_bundleFailed', { params: { reason: safeReason } }))\n }\n }\n return { name: 'docker-ssh', deploy: deploySafely }\n}\n","/**\n * @h-ai/deploy — Vercel 部署 Provider\n *\n * 封装 Vercel REST API,实现 DeployProvider 接口。 使用原生 fetch 调用,零外部 SDK 依赖。\n * @module deploy-provider-vercel\n */\n\nimport type { HaiError, HaiErrorDef, HaiResult } from '@h-ai/core'\nimport type { DeployProvider } from '../deploy-internal-types.js'\nimport type { DeployResult } from '../deploy-types.js'\nimport { createHash } from 'node:crypto'\nimport { readdirSync, readFileSync, statSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provider-vercel' })\n\n/** Vercel API 基址 */\nconst VERCEL_API = 'https://api.vercel.com'\n\n/** 部署状态轮询间隔(毫秒) */\nconst POLL_INTERVAL = 3000\n\n/** 部署状态轮询最大次数 */\nconst MAX_POLL_ATTEMPTS = 60\n\n// ─── 内部工具 ───\n\n/** Vercel API 错误,保留状态码用于区分 404 与真实失败 */\nclass VercelApiError extends Error {\n constructor(readonly status: number) {\n super(deployM('deploy_apiError', { params: { service: 'Vercel', status: String(status) } }))\n }\n}\n\n/** 构造标准错误对象 */\nfunction toDeployError(codeDef: HaiErrorDef, messageKey: string, error: unknown): HaiError {\n return {\n ...codeDef,\n message: deployM(messageKey as Parameters<typeof deployM>[0], {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n cause: error,\n }\n}\n\n/**\n * 发送 Vercel API 请求\n *\n * @param token - API Token\n * @param path - API 路径(如 /v2/user)\n * @param options - fetch 选项\n * @returns 解析后的 JSON 响应\n */\nasync function vercelFetch<T>(token: string, path: string, options?: RequestInit): Promise<T> {\n const url = `${VERCEL_API}${path}`\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new VercelApiError(response.status)\n }\n\n return response.json() as Promise<T>\n}\n\n/**\n * 递归收集目录中的所有文件\n *\n * @param dir - 目录路径\n * @param baseDir - 基础目录(用于计算相对路径)\n * @returns 文件相对路径列表\n */\nfunction collectFiles(dir: string, baseDir: string): string[] {\n const results: string[] = []\n const entries = readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...collectFiles(fullPath, baseDir))\n }\n else {\n results.push(relative(baseDir, fullPath).split(sep).join('/'))\n }\n }\n\n return results\n}\n\n// ─── Provider 工厂 ───\n\n/**\n * 创建 Vercel 部署 Provider\n * @returns DeployProvider 实例\n * @example 模块内部上下文\n * ```ts\n * const provider = createVercelProvider()\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const result = await provider.authenticate(token)\n * if (!result.success) throw new Error(result.error.message)\n * ```\n */\nexport function createVercelProvider(): DeployProvider {\n let token: string | null = null\n\n return {\n name: 'vercel',\n\n async authenticate(apiToken: string): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Vercel')\n try {\n const user = await vercelFetch<{ user: { username: string, email: string } }>(\n apiToken,\n '/v2/user',\n )\n token = apiToken\n const username = user.user.username || user.user.email\n logger.info('Vercel authenticated', { user: username })\n return ok(username)\n }\n catch (error) {\n logger.error('Vercel authentication failed', { error })\n return err(toDeployError(HaiDeployError.AUTH_FAILED, 'deploy_authFailed', error))\n }\n },\n\n async createProject(projectName: string): Promise<HaiResult<string>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Creating Vercel project', { projectName })\n try {\n // 先查找已有项目\n const existingId = await findExistingProject(token, projectName)\n if (existingId !== null) {\n logger.info('Vercel project found', { projectName, projectId: existingId })\n return ok(existingId)\n }\n\n try {\n const project = await vercelFetch<{ id: string }>(\n token,\n '/v11/projects',\n {\n method: 'POST',\n body: JSON.stringify({\n name: projectName,\n framework: 'sveltekit',\n }),\n },\n )\n logger.info('Vercel project created', { projectName, projectId: project.id })\n return ok(project.id)\n }\n catch (error) {\n // 官方文档说明同名项目创建会返回 409;遇到并发竞争时回查现有项目即可实现幂等。\n if (error instanceof VercelApiError && error.status === 409) {\n const concurrentProjectId = await findExistingProject(token, projectName)\n if (concurrentProjectId !== null) {\n logger.info('Vercel project reused after create conflict', {\n projectName,\n projectId: concurrentProjectId,\n })\n return ok(concurrentProjectId)\n }\n }\n throw error\n }\n }\n catch (error) {\n logger.error('Vercel project creation failed', { projectName, error })\n return err(toDeployError(HaiDeployError.PROJECT_CREATE_FAILED, 'deploy_projectCreateFailed', error))\n }\n },\n\n async setEnvVars(projectId: string, envVars: Record<string, string>): Promise<HaiResult<void>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Setting Vercel env vars', { projectId, count: Object.keys(envVars).length })\n try {\n const envEntries = Object.entries(envVars).map(([key, value]) => ({\n key,\n value,\n type: 'encrypted' as const,\n target: ['production', 'preview', 'development'],\n }))\n\n // Vercel 官方 `upsert=true` 支持按 key 覆盖已有环境变量,避免重复部署时报“已存在”。\n await vercelFetch(\n token,\n `/v10/projects/${projectId}/env?upsert=true`,\n {\n method: 'POST',\n body: JSON.stringify(envEntries),\n },\n )\n logger.info('Vercel env vars set', { projectId, count: envEntries.length })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Vercel env vars setup failed', { projectId, error })\n return err(toDeployError(HaiDeployError.ENV_VAR_FAILED, 'deploy_envVarFailed', error))\n }\n },\n\n async deploy(projectId: string, outputDir: string): Promise<HaiResult<DeployResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Deploying to Vercel', { projectId, outputDir })\n try {\n // 只接受 Build Output API v3;不把普通源码交给平台重新构建。\n const outputConfig = JSON.parse(readFileSync(join(outputDir, 'config.json'), 'utf8')) as { version?: unknown }\n if (outputConfig.version !== 3)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n // 收集所有文件\n const filePaths = collectFiles(outputDir, outputDir)\n const files: Array<{ file: string, sha: string, size: number }> = []\n\n // 上传每个文件\n for (const filePath of filePaths) {\n const fullPath = join(outputDir, filePath)\n const content = readFileSync(fullPath)\n const sha = createHash('sha1').update(content).digest('hex')\n const size = statSync(fullPath).size\n\n await uploadFile(token, content, sha)\n files.push({ file: `.vercel/output/${filePath}`, sha, size })\n }\n\n logger.debug('Files uploaded', { count: files.length })\n\n // 创建部署\n const deployment = await vercelFetch<{ id: string, url: string }>(\n token,\n '/v13/deployments?prebuilt=1',\n {\n method: 'POST',\n body: JSON.stringify({\n name: projectId,\n files,\n version: 2,\n project: projectId,\n projectSettings: { framework: null, buildCommand: '', installCommand: '' },\n }),\n },\n )\n\n // 轮询部署状态\n const finalStatus = await pollDeploymentStatus(token, deployment.id)\n\n const result: DeployResult = {\n url: `https://${deployment.url}`,\n deploymentId: deployment.id,\n status: finalStatus,\n envVarsSet: [],\n }\n\n logger.info('Vercel deployment complete', {\n deploymentId: deployment.id,\n url: result.url,\n status: finalStatus,\n })\n\n return ok(result)\n }\n catch (error) {\n logger.error('Vercel deployment failed', { projectId, error })\n return err(toDeployError(HaiDeployError.UPLOAD_FAILED, 'deploy_uploadFailed', error))\n }\n },\n }\n}\n\n// ─── 内部辅助 ───\n\n/**\n * 查找已有的 Vercel 项目\n *\n * @param token - API Token\n * @param projectName - 项目名称\n * @returns 项目 ID,不存在时返回 null\n */\nasync function findExistingProject(token: string, projectName: string): Promise<string | null> {\n try {\n const project = await vercelFetch<{ id: string }>(token, `/v10/projects/${projectName}`)\n return project.id\n }\n catch (error) {\n if (error instanceof VercelApiError && error.status === 404) {\n return null\n }\n throw error\n }\n}\n\n/**\n * 上传单个文件到 Vercel\n *\n * @param token - API Token\n * @param content - 文件内容\n * @param sha - 文件 SHA1 哈希\n */\nasync function uploadFile(token: string, content: Uint8Array, sha: string): Promise<void> {\n const url = `${VERCEL_API}/v2/files`\n const uploadContent = new Uint8Array(content)\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/octet-stream',\n 'x-vercel-digest': sha,\n },\n body: new Blob([uploadContent]),\n })\n\n if (!response.ok && response.status !== 409) {\n // 409 表示文件已存在,可忽略\n throw new Error(deployM('deploy_fileUploadFailed', { params: { status: String(response.status) } }))\n }\n}\n\n/**\n * 轮询部署状态直到完成\n *\n * @param token - API Token\n * @param deploymentId - 部署 ID\n * @returns 最终状态\n */\nasync function pollDeploymentStatus(\n token: string,\n deploymentId: string,\n): Promise<'ready' | 'building' | 'error'> {\n for (let i = 0; i < MAX_POLL_ATTEMPTS; i++) {\n const deployment = await vercelFetch<{ readyState: string }>(\n token,\n `/v13/deployments/${deploymentId}`,\n )\n\n if (deployment.readyState === 'READY') {\n return 'ready'\n }\n if (deployment.readyState === 'ERROR' || deployment.readyState === 'CANCELED') {\n return 'error'\n }\n\n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL))\n }\n\n // 超时仍在构建\n return 'building'\n}\n","/**\n * @h-ai/deploy — Aliyun SMS Provisioner\n *\n * 验证阿里云 API 凭证用于短信服务。 阿里云短信资源(签名/模板)通常在控制台预配置,此 Provisioner 仅验证凭证。\n * @module deploy-provisioner-aliyun\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-aliyun' })\n\n/**\n * 创建 Aliyun SMS Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const accessKeyId = process.env.HAI_DEPLOY_SERVICES_SMS_ACCESSKEYID\n * if (!accessKeyId) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_ACCESSKEYID privately')\n * const accessKeySecret = process.env.HAI_DEPLOY_SERVICES_SMS_ACCESSKEYSECRET\n * if (!accessKeySecret) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_ACCESSKEYSECRET privately')\n * const signName = process.env.HAI_DEPLOY_SERVICES_SMS_SIGNNAME\n * if (!signName) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_SIGNNAME privately')\n * const provisioner = createAliyunProvisioner()\n * const authenticated = await provisioner.authenticate({ accessKeyId, accessKeySecret, signName })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createAliyunProvisioner(): ServiceProvisioner {\n let accessKey: string | null = null\n let secretKey: string | null = null\n let signName = ''\n\n return {\n name: 'aliyun',\n serviceType: 'sms',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Aliyun')\n try {\n const akId = credentials.accessKeyId ?? credentials.access_key_id ?? credentials.access_key ?? ''\n const akSecret = credentials.accessKeySecret ?? credentials.access_key_secret ?? credentials.secret_key ?? ''\n\n if (!akId || !akSecret || !credentials.signName) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'accessKeyId, accessKeySecret, signName' } }))\n }\n\n accessKey = akId\n secretKey = akSecret\n signName = credentials.signName\n logger.info('Aliyun authenticated', { accessKeyId: `${akId.slice(0, 6)}***` })\n return ok(akId)\n }\n catch (error) {\n logger.error('Aliyun authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(_appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!accessKey || !secretKey) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Aliyun SMS service')\n\n // 阿里云短信不支持 API 创建资源,仅返回凭证作为环境变量\n return ok({\n serviceType: 'sms',\n provisionerName: 'aliyun',\n resourceStatus: 'reused',\n envVars: {\n HAI_REACH_PROVIDERS: JSON.stringify([{ name: 'sms', type: 'aliyun-sms', accessKeyId: accessKey, accessKeySecret: secretKey, signName }]),\n },\n resourceInfo: 'aliyun:verify-only',\n })\n },\n }\n}\n","/**\n * @h-ai/deploy — Neon PostgreSQL Provisioner\n *\n * 通过 Neon REST API 自动创建 PostgreSQL 数据库。\n * @module deploy-provisioner-neon\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { recoveryFailure } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-neon' })\n\n/** Neon API 基址 */\nconst NEON_API = 'https://console.neon.tech/api/v2'\n\n/** Neon 新建项目默认生成的数据库名。 */\nconst DEFAULT_NEON_DATABASE_NAME = 'neondb'\n\n/** Neon 新建项目默认生成的角色名。 */\nconst DEFAULT_NEON_ROLE_NAME = 'neondb_owner'\n\n/**\n * Neon 列表中用于按名称核对现有资源的字段。\n * @example 模块内部上下文\n * ```ts\n * const project: NeonProjectSummary = { id: 'project-shop', name: 'shop' }\n * ```\n */\ninterface NeonProjectSummary {\n id: string\n name: string\n}\n\n/**\n * 列表字段可缺失;调用方不能将请求失败解释为资源不存在。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonProjectsResponse = { projects: [{ id: 'project-shop', name: 'shop' }] }\n * const existing = response.projects?.find(project => project.name === 'shop')\n * ```\n */\ninterface NeonProjectsResponse {\n projects?: NeonProjectSummary[]\n}\n\n/**\n * 创建回执的可选形状;连接 URI 可能包含口令,不得输出。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonCreateProjectResponse = { project: { id: 'project-shop' } }\n * const id = response.project?.id // 无连接 URI 时再按已确认 ID 读取,不能重新创建。\n * ```\n */\ninterface NeonCreateProjectResponse {\n connection_uris?: Array<{ connection_uri?: string }>\n project?: { id?: string }\n}\n\n/**\n * 连接读取回执;真实 URI 可能含密码,必须作为私有配置处理。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonConnectionUriResponse = { uri: 'postgresql://app@db.example.org/shop' }\n * const present = Boolean(response.uri)\n * ```\n */\ninterface NeonConnectionUriResponse {\n uri?: string\n}\n\n/** 统一发起 Neon API 请求。 */\nasync function neonFetch<T>(token: string, path: string, options?: RequestInit): Promise<T> {\n const response = await fetch(`${NEON_API}${path}`, {\n ...options,\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Neon', status: String(response.status) } }))\n }\n\n return response.json() as Promise<T>\n}\n\n/** 列出当前账号下的 Neon 项目。 */\nasync function listNeonProjects(token: string): Promise<NeonProjectSummary[]> {\n const data = await neonFetch<NeonProjectsResponse>(token, '/projects')\n return data.projects ?? []\n}\n\n/** 按名称查找已有的 Neon 项目。 */\nasync function findExistingNeonProject(token: string, projectName: string): Promise<NeonProjectSummary | null> {\n const projects = await listNeonProjects(token)\n return projects.find(project => project.name === projectName) ?? null\n}\n\n/**\n * 获取现有项目的连接串。\n *\n * Neon 官方 OpenAPI 提供 `GET /projects/{project_id}/connection_uri`。\n * 这里使用创建项目时的默认数据库/角色名,保证本模块创建的项目可被幂等复用。\n */\nasync function getNeonConnectionUri(token: string, projectId: string): Promise<string> {\n const query = new URLSearchParams({\n database_name: DEFAULT_NEON_DATABASE_NAME,\n role_name: DEFAULT_NEON_ROLE_NAME,\n })\n const data = await neonFetch<NeonConnectionUriResponse>(\n token,\n `/projects/${projectId}/connection_uri?${query.toString()}`,\n { headers: { 'Content-Type': 'application/json' } },\n )\n\n if (!data.uri) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Neon' } }))\n }\n\n return data.uri\n}\n\n/** 构建统一的 Neon 开通结果。 */\nfunction buildNeonProvisionResult(projectId: string, connectionUri: string, resourceStatus: 'created' | 'reused'): ProvisionResult {\n return {\n serviceType: 'db',\n provisionerName: 'neon',\n resourceStatus,\n envVars: {\n HAI_DB: JSON.stringify({ type: 'postgresql', url: connectionUri, database: decodeURIComponent(new URL(connectionUri).pathname.slice(1)) }),\n },\n resourceInfo: `neon-project:${projectId}`,\n }\n}\n\n/**\n * 创建 Neon PostgreSQL Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_DB_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_DB_APIKEY privately')\n * const provisioner = createNeonProvisioner()\n * const authenticated = await provisioner.authenticate({ apiKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createNeonProvisioner(): ServiceProvisioner {\n let token: string | null = null\n\n return {\n name: 'neon',\n serviceType: 'db',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Neon')\n try {\n const apiToken = credentials.apiKey ?? credentials.token ?? credentials.api_key ?? ''\n if (!apiToken) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'token' } }))\n }\n\n await listNeonProjects(apiToken)\n token = apiToken\n logger.info('Neon authenticated')\n return ok('neon-user')\n }\n catch (error) {\n logger.error('Neon authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Neon database', { appName })\n let resource: { resourceInfo: string, resourceStatus: 'created' | 'reused' } | undefined\n try {\n const projectName = `${appName}-db`\n\n const existingProject = await findExistingNeonProject(token, projectName)\n if (existingProject !== null) {\n resource = { resourceInfo: `neon-project:${existingProject.id}`, resourceStatus: 'reused' }\n const connectionUri = await getNeonConnectionUri(token, existingProject.id)\n logger.info('Neon project reused', {\n projectId: existingProject.id,\n projectName,\n })\n return ok(buildNeonProvisionResult(existingProject.id, connectionUri, 'reused'))\n }\n\n const data = await neonFetch<NeonCreateProjectResponse>(token, '/projects', {\n method: 'POST',\n body: JSON.stringify({\n project: {\n name: projectName,\n pg_version: 16,\n },\n }),\n })\n\n const projectId = data.project?.id ?? ''\n if (projectId)\n resource = { resourceInfo: `neon-project:${projectId}`, resourceStatus: 'created' }\n const connectionUri = data.connection_uris?.[0]?.connection_uri ?? ''\n if (!projectId || !connectionUri) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Neon' } }))\n }\n\n logger.info('Neon database provisioned', { projectId })\n\n return ok(buildNeonProvisionResult(projectId, connectionUri, 'created'))\n }\n catch (error) {\n logger.error('Neon provisioning failed', { appName })\n if (resource) {\n return recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: '' }, {\n projectName: appName,\n stage: 'provision:db',\n resources: [{ serviceType: 'db', provisionerName: 'neon', ...resource }],\n })\n }\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'neon',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — Cloudflare R2 Provisioner\n *\n * 通过 Cloudflare API 自动创建 R2 存储桶。\n * @module deploy-provisioner-r2\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-r2' })\n\n/** Cloudflare API 基址 */\nconst CF_API = 'https://api.cloudflare.com/client/v4'\n\n/**\n * 创建 Cloudflare R2 Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const accountId = process.env.HAI_DEPLOY_SERVICES_STORAGE_ACCOUNTID\n * if (!accountId) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_ACCOUNTID privately')\n * const apiToken = process.env.HAI_DEPLOY_SERVICES_STORAGE_APITOKEN\n * if (!apiToken) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_APITOKEN privately')\n * const accessKeyId = process.env.HAI_DEPLOY_SERVICES_STORAGE_ACCESSKEYID\n * if (!accessKeyId) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_ACCESSKEYID privately')\n * const secretAccessKey = process.env.HAI_DEPLOY_SERVICES_STORAGE_SECRETACCESSKEY\n * if (!secretAccessKey) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_SECRETACCESSKEY privately')\n * const provisioner = createR2Provisioner()\n * const authenticated = await provisioner.authenticate({ accountId, apiToken, accessKeyId, secretAccessKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createR2Provisioner(): ServiceProvisioner {\n let token: string | null = null\n let accountId: string | null = null\n let accessKey = ''\n let secretKey = ''\n\n return {\n name: 'r2',\n serviceType: 'storage',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Cloudflare')\n try {\n const acctId = credentials.accountId ?? credentials.account_id ?? ''\n const apiTok = credentials.apiToken ?? credentials.api_token ?? credentials.token ?? ''\n if (!acctId || !apiTok || !credentials.accessKeyId || !credentials.secretAccessKey) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'accountId, apiToken, accessKeyId, secretAccessKey' } }))\n }\n\n const res = await fetch(`${CF_API}/accounts/${acctId}/r2/buckets`, {\n headers: { Authorization: `Bearer ${apiTok}` },\n })\n if (!res.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Cloudflare', status: String(res.status) } }))\n }\n\n accountId = acctId\n token = apiTok\n accessKey = credentials.accessKeyId\n secretKey = credentials.secretAccessKey\n logger.info('Cloudflare R2 authenticated', { accountId: acctId })\n return ok(acctId)\n }\n catch (error) {\n logger.error('Cloudflare R2 authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token || !accountId) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n const bucketName = `${appName}-storage`.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n\n logger.debug('Provisioning R2 bucket', { appName, bucketName })\n try {\n // 创建桶\n const createRes = await fetch(\n `${CF_API}/accounts/${accountId}/r2/buckets`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ name: bucketName }),\n },\n )\n\n // 409 表示桶已存在,可继续\n if (!createRes.ok && createRes.status !== 409) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Cloudflare', status: String(createRes.status) } }))\n }\n\n logger.info('R2 bucket provisioned', { bucketName })\n\n return ok({\n serviceType: 'storage',\n provisionerName: 'r2',\n resourceStatus: createRes.status === 409 ? 'reused' : 'created',\n envVars: {\n HAI_STORAGE: JSON.stringify({\n type: 's3',\n endpoint: `https://${accountId}.r2.cloudflarestorage.com`,\n bucket: bucketName,\n region: 'auto',\n accessKeyId: accessKey,\n secretAccessKey: secretKey,\n }),\n },\n resourceInfo: `r2-bucket:${bucketName}`,\n })\n }\n catch (error) {\n logger.error('R2 provisioning failed', { appName, error })\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'r2',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — Resend Email Provisioner\n *\n * 通过 Resend REST API 验证 API Key 并获取域信息。 Resend 不支持通过 API 创建账户,此 Provisioner 仅验证已有凭证。\n * @module deploy-provisioner-resend\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-resend' })\n\n/** Resend API 基址 */\nconst RESEND_API = 'https://api.resend.com'\n\n/**\n * 创建 Resend Email Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_EMAIL_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_EMAIL_APIKEY privately')\n * const from = process.env.HAI_DEPLOY_SERVICES_EMAIL_FROM\n * if (!from) throw new Error('Provide HAI_DEPLOY_SERVICES_EMAIL_FROM privately')\n * const provisioner = createResendProvisioner()\n * const authenticated = await provisioner.authenticate({ apiKey, from })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createResendProvisioner(): ServiceProvisioner {\n let token: string | null = null\n let from = ''\n\n return {\n name: 'resend',\n serviceType: 'email',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Resend')\n try {\n const apiToken = credentials.apiKey ?? credentials.api_key ?? credentials.token ?? ''\n if (!apiToken || !credentials.from) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'apiKey, from' } }))\n }\n\n const res = await fetch(`${RESEND_API}/domains`, {\n headers: { Authorization: `Bearer ${apiToken}` },\n })\n if (!res.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Resend', status: String(res.status) } }))\n }\n token = apiToken\n from = credentials.from\n logger.info('Resend authenticated')\n return ok('resend-user')\n }\n catch (error) {\n logger.error('Resend authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(_appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Resend email service')\n\n // Resend 不支持 API 创建资源,仅返回凭证作为环境变量\n return ok({\n serviceType: 'email',\n provisionerName: 'resend',\n resourceStatus: 'reused',\n envVars: {\n HAI_REACH_PROVIDERS: JSON.stringify([{ name: 'email', type: 'smtp', host: 'smtp.resend.com', port: 465, secure: true, user: 'resend', pass: token, from }]),\n },\n resourceInfo: 'resend:verify-only',\n })\n },\n }\n}\n","/**\n * @h-ai/deploy — Upstash Redis Provisioner\n *\n * 通过 Upstash REST API 自动创建 Redis 数据库。\n * @module deploy-provisioner-upstash\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { Buffer } from 'node:buffer'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { deployM } from '../deploy-i18n.js'\nimport { recoveryFailure } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-upstash' })\n\n/** Upstash API 基址 */\nconst UPSTASH_API = 'https://api.upstash.com'\n\n/**\n * 供应商 API 的部分字段形状;缺少连接凭据时不能声称已有连接可用。\n * @example 模块内部上下文\n * ```ts\n * const database: UpstashDatabase = { database_id: 'redis-shop', database_name: 'shop', endpoint: 'redis.example.org', port: 6379 }\n * const id = database.database_id\n * ```\n */\ninterface UpstashDatabase {\n database_id?: string\n database_name?: string\n endpoint?: string\n port?: number\n password?: string\n}\n\n/** 构建 Upstash Developer API 的 Basic Auth 请求头。 */\nfunction createUpstashAuthHeader(email: string, apiKey: string): string {\n return `Basic ${Buffer.from(`${email}:${apiKey}`).toString('base64')}`\n}\n\n/** 统一发起 Upstash Developer API 请求。 */\nasync function upstashFetch<T>(\n email: string,\n apiKey: string,\n path: string,\n options?: RequestInit,\n): Promise<T> {\n const response = await fetch(`${UPSTASH_API}${path}`, {\n ...options,\n headers: {\n 'Authorization': createUpstashAuthHeader(email, apiKey),\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Upstash', status: String(response.status) } }))\n }\n\n return response.json() as Promise<T>\n}\n\n/** 列出当前账号下的所有 Upstash 数据库。 */\nasync function listUpstashDatabases(email: string, apiKey: string): Promise<UpstashDatabase[]> {\n return upstashFetch<UpstashDatabase[]>(email, apiKey, '/v2/redis/databases')\n}\n\n/** 按数据库名查找已有资源。 */\nasync function findExistingUpstashDatabase(\n email: string,\n apiKey: string,\n databaseName: string,\n): Promise<UpstashDatabase | null> {\n const databases = await listUpstashDatabases(email, apiKey)\n return databases.find(database => database.database_name === databaseName) ?? null\n}\n\n/** 获取单个数据库详情。 */\nasync function getUpstashDatabase(email: string, apiKey: string, databaseId: string): Promise<UpstashDatabase> {\n return upstashFetch<UpstashDatabase>(email, apiKey, `/v2/redis/database/${databaseId}`)\n}\n\n/** 将 Upstash 响应转换为 deploy 统一结果。 */\nfunction buildUpstashProvisionResult(database: UpstashDatabase, resourceStatus: 'created' | 'reused'): ProvisionResult {\n const databaseId = database.database_id ?? ''\n\n if (!databaseId || !database.endpoint || !database.password || !database.port) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Upstash' } }))\n }\n\n return {\n serviceType: 'cache',\n provisionerName: 'upstash',\n resourceStatus,\n envVars: {\n HAI_CACHE: JSON.stringify({ type: 'redis', url: `rediss://default:${encodeURIComponent(database.password)}@${database.endpoint}:${database.port}` }),\n },\n resourceInfo: `upstash-db:${databaseId}`,\n }\n}\n\n/**\n * 创建 Upstash Redis Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const email = process.env.HAI_DEPLOY_SERVICES_CACHE_EMAIL\n * if (!email) throw new Error('Provide HAI_DEPLOY_SERVICES_CACHE_EMAIL privately')\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_CACHE_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_CACHE_APIKEY privately')\n * const provisioner = createUpstashProvisioner()\n * const authenticated = await provisioner.authenticate({ email, apiKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createUpstashProvisioner(): ServiceProvisioner {\n let apiKey: string | null = null\n let email: string | null = null\n\n return {\n name: 'upstash',\n serviceType: 'cache',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Upstash')\n try {\n const userEmail = credentials.email ?? ''\n const userKey = credentials.apiKey ?? credentials.api_key ?? credentials.token ?? ''\n if (!userEmail || !userKey) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'email, api_key' } }))\n }\n\n await listUpstashDatabases(userEmail, userKey)\n\n email = userEmail\n apiKey = userKey\n logger.info('Upstash authenticated', { email: userEmail })\n return ok(userEmail)\n }\n catch (error) {\n logger.error('Upstash authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!apiKey || !email) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Upstash Redis', { appName })\n let resource: { resourceInfo: string, resourceStatus: 'created' | 'reused' } | undefined\n try {\n const databaseName = `${appName}-cache`\n\n const existingDatabase = await findExistingUpstashDatabase(email, apiKey, databaseName)\n if (existingDatabase !== null) {\n const databaseId = existingDatabase.database_id ?? ''\n if (!databaseId) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Upstash' } }))\n }\n\n resource = { resourceInfo: `upstash-db:${databaseId}`, resourceStatus: 'reused' }\n const detail = await getUpstashDatabase(email, apiKey, databaseId)\n logger.info('Upstash Redis reused', { databaseId, databaseName })\n return ok(buildUpstashProvisionResult({ ...existingDatabase, ...detail }, 'reused'))\n }\n\n const data = await upstashFetch<UpstashDatabase>(email, apiKey, '/v2/redis/database', {\n method: 'POST',\n body: JSON.stringify({\n name: databaseName,\n region: 'global',\n tls: true,\n }),\n })\n\n if (data.database_id)\n resource = { resourceInfo: `upstash-db:${data.database_id}`, resourceStatus: 'created' }\n logger.info('Upstash Redis provisioned', { databaseId: data.database_id })\n\n return ok(buildUpstashProvisionResult(data, 'created'))\n }\n catch (error) {\n logger.error('Upstash provisioning failed', { appName })\n if (resource) {\n return recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: '' }, {\n projectName: appName,\n stage: 'provision:cache',\n resources: [{ serviceType: 'cache', provisionerName: 'upstash', ...resource }],\n })\n }\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'upstash',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — 模块主入口\n *\n * 提供 deploy 单例对象,暴露完整的自动化部署 API。\n * @module deploy-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ContainerDeployProvider } from './container/deploy-container-types.js'\nimport type { DeployConfig, DeployConfigInput } from './deploy-config.js'\nimport type { DeployProvider, ServiceProvisioner } from './deploy-internal-types.js'\nimport type {\n DeployAppOptions,\n DeployCredentialOperations,\n DeployFunctions,\n DeployRecoveryInfo,\n DeployResult,\n DeployScanOptions,\n ProvisionResult,\n ScanResult,\n ServiceType,\n} from './deploy-types.js'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { readDeploymentArtifact } from './deploy-artifact.js'\nimport { DeployConfigSchema } from './deploy-config.js'\nimport {\n getCredentialsPath,\n loadCredentials,\n saveCredential,\n saveCredentials,\n} from './deploy-credentials.js'\nimport { loadDeploymentEnvironment, saveDeploymentEnvironment } from './deploy-environment.js'\nimport { normalizeProjectName, resolveArtifactDirectory, resolveOutputDir, resolveProjectDirectory, usesDefaultMiddleware } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { mergeManagedMiddlewareConfig } from './deploy-middleware-config.js'\nimport { getDeployRecovery, recoveryFailure } from './deploy-recovery.js'\nimport { scanApp } from './deploy-scanner.js'\nimport { HaiDeployError } from './deploy-types.js'\nimport { createDockerSshProvider } from './providers/deploy-provider-docker-ssh.js'\nimport { createVercelProvider } from './providers/deploy-provider-vercel.js'\nimport { createAliyunProvisioner } from './provisioners/deploy-provisioner-aliyun.js'\nimport { createNeonProvisioner } from './provisioners/deploy-provisioner-neon.js'\nimport { createR2Provisioner } from './provisioners/deploy-provisioner-r2.js'\nimport { createResendProvisioner } from './provisioners/deploy-provisioner-resend.js'\nimport { createUpstashProvisioner } from './provisioners/deploy-provisioner-upstash.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'main' })\n\n// ─── 内部状态 ───\n\nlet currentConfig: DeployConfig | null = null\nlet currentProvider: DeployProvider | null = null\nlet currentContainerProvider: ContainerDeployProvider | null = null\nconst currentProvisioners: Map<ServiceType, ServiceProvisioner> = new Map()\n\n/** 并发初始化防护标志 */\nlet initInProgress = false\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiDeployError.NOT_INITIALIZED,\n () => deployM('deploy_notInitialized'),\n)\n\n// ─── Provider 工厂 ───\n\n/**\n * 根据配置类型创建对应的 DeployProvider\n *\n * @param type - Provider 类型\n * @returns DeployProvider 实例\n */\nfunction createProviderByType(type: string): DeployProvider {\n switch (type) {\n case 'vercel':\n return createVercelProvider()\n default:\n throw new Error(deployM('deploy_unsupportedProviderType', { params: { type } }))\n }\n}\n\n// ─── Provisioner 工厂 ───\n\n/**\n * 根据 provisioner 名称创建对应的 ServiceProvisioner\n *\n * @param provisioner - Provisioner 标识\n * @returns ServiceProvisioner 实例\n */\nfunction createProvisionerByName(provisioner: string): ServiceProvisioner {\n switch (provisioner) {\n case 'neon':\n return createNeonProvisioner()\n case 'upstash':\n return createUpstashProvisioner()\n case 'cloudflare-r2':\n return createR2Provisioner()\n case 'resend':\n return createResendProvisioner()\n case 'aliyun':\n return createAliyunProvisioner()\n default:\n throw new Error(deployM('deploy_unsupportedProvisionerType', { params: { type: provisioner } }))\n }\n}\n\n/**\n * 从配置中提取 provisioner 凭证并转为 Record<string, string>\n *\n * @param serviceConfig - 服务配置对象\n * @returns 凭证键值对\n */\nfunction extractCredentials(serviceConfig: Record<string, unknown>): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(serviceConfig)) {\n if (key !== 'provisioner' && typeof value === 'string') {\n result[key] = value\n }\n }\n return result\n}\n\n/**\n * Deploy 凭证子功能。\n *\n * 这些操作仅处理本地 `~/.hai/credentials.yml`,供 CLI 在读取项目 `hai.json` 的部署配置\n * 之前注入 `HAI_DEPLOY_*` 环境变量,因此不依赖 `deploy.init()`。\n */\nconst deployCredentials: DeployCredentialOperations = {\n getPath: () => getCredentialsPath(),\n load: () => loadCredentials(),\n save: (key: string, value: string) => saveCredential(key, value),\n saveAll: (entries: Record<string, string>) => saveCredentials(entries),\n}\n\n/** 合并 Provisioner 输出环境变量,并聚合 HAI_REACH_PROVIDERS 数组。 */\nfunction mergeProvisionEnv(results: ProvisionResult[], scan?: ScanResult, options?: DeployAppOptions): Record<string, string> {\n const env: Record<string, string> = {}\n const reachRequirements = scan?.middlewares?.filter(item => item.configName === 'reach') ?? []\n const reachProviders: unknown[] = reachRequirements.map(item => item.config)\n let hasReachOutput = false\n for (const prov of results) {\n if (prov.envVars.HAI_REACH_PROVIDERS) {\n hasReachOutput = true\n const supplied = JSON.parse(prov.envVars.HAI_REACH_PROVIDERS) as Record<string, unknown>[]\n for (const provider of supplied) {\n const targets = reachRequirements.filter((item) => {\n const mode = options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.[item.service]\n return item.service === prov.serviceType && (!mode || mode === 'default')\n })\n if (targets.length) {\n for (const target of targets)\n reachProviders[reachRequirements.indexOf(target)] = { ...mergeManagedMiddlewareConfig(target, provider), name: target.config.name ?? provider.name }\n }\n else {\n reachProviders.push(provider)\n }\n }\n }\n for (const [name, value] of Object.entries(prov.envVars)) {\n const requirement = scan?.middlewares?.find(item => item.envPrefix === name)\n env[name] = requirement ? JSON.stringify(mergeManagedMiddlewareConfig(requirement, JSON.parse(value))) : value\n }\n }\n if (hasReachOutput)\n env.HAI_REACH_PROVIDERS = JSON.stringify(reachProviders)\n return env\n}\n\n// ─── 模块单例 ───\n\n/**\n * Deploy 模块单例\n * 每次 init 检查 HaiResult;只打包不会连接 SSH,成功打包也不代表服务器已部署。远端 unknown 必须先核对匹配部署 ID 的结果,不能盲目重试。\n * @example\n * ```ts\n * import { deploy, getDeployCommandState } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 当前项目已有镜像产物与部署环境;只打包,不连接服务器。\n * const result = await deploy.deployApp(process.cwd(), { environment: 'prod', bundleOnly: true })\n * if (!result.success) {\n * const state = getDeployCommandState(result.error)\n * if (state?.remoteExecution === 'unknown') {\n * process.stderr.write('Inspect the matching server result before retrying\\n')\n * }\n * throw new Error(result.error.message)\n * }\n * if (result.data.status === 'packaged') {\n * const bundle = result.data.bundlePath\n * }\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\nexport const deploy: DeployFunctions = {\n credentials: deployCredentials,\n\n async init(config: DeployConfigInput): Promise<HaiResult<void>> {\n // 并发初始化防护:避免多次 init 同时执行导致资源泄漏\n if (initInProgress) {\n logger.warn('Deploy init already in progress, skipping concurrent call')\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', { params: { error: 'init already in progress' } }),\n )\n }\n initInProgress = true\n\n try {\n if (currentProvider || currentContainerProvider) {\n logger.warn('Deploy module is already initialized, reinitializing')\n await deploy.close()\n }\n\n logger.info('Initializing deploy module')\n\n const parseResult = DeployConfigSchema.safeParse(config)\n if (!parseResult.success) {\n logger.error('Deploy config validation failed', { error: parseResult.error.message })\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', { params: { error: parseResult.error.message } }),\n parseResult.error,\n )\n }\n const parsed = parseResult.data\n\n try {\n // 创建部署 Provider:docker-ssh 走容器路径(无远程认证),其余走平台路径并即时认证\n let provider: DeployProvider | null = null\n let containerProvider: ContainerDeployProvider | null = null\n if (parsed.provider.type === 'docker-ssh') {\n containerProvider = createDockerSshProvider(parsed.provider, parsed.container)\n logger.info('Container deploy provider ready', { provider: 'docker-ssh', host: parsed.provider.ssh?.host })\n }\n else {\n provider = createProviderByType(parsed.provider.type)\n const authResult = await provider.authenticate(parsed.provider.token)\n if (!authResult.success) {\n return err(authResult.error)\n }\n logger.info('Provider authenticated', { provider: parsed.provider.type, user: authResult.data })\n }\n\n // 创建 Provisioners(两类 Provider 均可复用云资源开通)\n currentProvisioners.clear()\n if (parsed.services) {\n const serviceEntries = Object.entries(parsed.services) as Array<[ServiceType, Record<string, unknown> | undefined]>\n for (const [serviceType, serviceConfig] of serviceEntries) {\n if (!serviceConfig)\n continue\n\n const provisioner = createProvisionerByName(serviceConfig.provisioner as string)\n const credentials = extractCredentials(serviceConfig as Record<string, unknown>)\n const provAuthResult = await provisioner.authenticate(credentials)\n if (!provAuthResult.success) {\n logger.error('Provisioner authentication failed', {\n service: serviceType,\n provisioner: (serviceConfig as Record<string, unknown>).provisioner,\n })\n currentProvisioners.clear()\n return err(provAuthResult.error)\n }\n logger.info('Provisioner authenticated', {\n service: serviceType,\n user: provAuthResult.data,\n })\n currentProvisioners.set(serviceType, provisioner)\n }\n }\n\n currentProvider = provider\n currentContainerProvider = containerProvider\n currentConfig = parsed\n logger.info('Deploy module initialized', {\n provider: parsed.provider.type,\n provisioners: [...currentProvisioners.keys()],\n })\n return ok(undefined)\n }\n catch (error) {\n // 清理部分赋值的状态\n currentProvider = null\n currentContainerProvider = null\n currentConfig = null\n currentProvisioners.clear()\n logger.error('Deploy module initialization failed', { error })\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n }\n finally {\n initInProgress = false\n }\n },\n\n async close(): Promise<void> {\n if (!currentProvider && !currentContainerProvider) {\n logger.info('Deploy module already closed, skipping')\n return\n }\n\n logger.info('Closing deploy module')\n currentProvider = null\n currentContainerProvider = null\n currentConfig = null\n currentProvisioners.clear()\n logger.info('Deploy module closed')\n },\n\n get config(): DeployConfig | null {\n return currentConfig\n },\n\n get isInitialized(): boolean {\n return currentProvider !== null || currentContainerProvider !== null\n },\n\n async scan(appDir: string, options?: DeployScanOptions): Promise<HaiResult<ScanResult>> {\n // scan 仅做本地文件分析,不依赖 Provider / Provisioner 初始化状态。\n logger.debug('Scanning application', { appDir })\n return scanApp(appDir, options)\n },\n\n async provisionAll(projectName: string, services?: ServiceType[]): Promise<HaiResult<ProvisionResult[]>> {\n if (!currentProvider && !currentContainerProvider) {\n return notInitialized.result()\n }\n\n logger.info('Provisioning all services', { projectName, count: currentProvisioners.size })\n const results: ProvisionResult[] = []\n\n for (const [serviceType, provisioner] of currentProvisioners) {\n if (services && !services.includes(serviceType))\n continue\n logger.debug('Provisioning service', { serviceType, provisioner: provisioner.name })\n const provResult = await provisioner.provision(projectName)\n if (!provResult.success) {\n logger.error('Service provisioning failed', {\n serviceType,\n provisioner: provisioner.name,\n code: provResult.error.code,\n })\n return recoveryFailure(provResult.error, {\n projectName,\n stage: `provision:${serviceType}`,\n resources: [\n ...results.map(({ envVars: _envVars, ...resource }) => resource),\n ...(getDeployRecovery(provResult.error)?.resources ?? [\n { serviceType, provisionerName: provisioner.name, resourceInfo: projectName, resourceStatus: 'unknown' as const },\n ]),\n ],\n })\n }\n results.push(provResult.data)\n logger.info('Service provisioned', { serviceType, provisioner: provisioner.name })\n }\n\n return ok(results)\n },\n\n async deployApp(\n appDir: string,\n options?: DeployAppOptions,\n ): Promise<HaiResult<DeployResult>> {\n if (!currentProvider && !currentContainerProvider) {\n return notInitialized.result()\n }\n\n if (options && 'projectName' in options && options.projectName !== undefined)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameOverrideRemoved'))\n\n logger.info('Starting deployment', { appDir, environment: options?.environment })\n\n // 1. 扫描应用\n const scanOptions = { ...options, environment: options?.environment ?? currentConfig?.environment }\n const scanResult = await scanApp(appDir, scanOptions)\n if (!scanResult.success) {\n return err(scanResult.error)\n }\n const scan = scanResult.data\n appDir = scan.appDir ?? appDir\n const environment = loadDeploymentEnvironment({ environment: scanOptions.environment ?? 'prod', envDir: scan.envDir ?? appDir, requireFile: scanOptions.environment !== undefined })\n if (!environment.success)\n return environment\n // SSH 密码允许引用自定义变量名;按配置来源排除,不能按密码值删除同值的应用配置。\n const connectionVariables = new Set<string>()\n const projectFile = join(resolveProjectDirectory(appDir), 'hai.json')\n if (existsSync(projectFile)) {\n try {\n const project: { deploy?: { provider?: { ssh?: { password?: unknown } } } } = JSON.parse(readFileSync(projectFile, 'utf8'))\n const reference = project?.deploy?.provider?.ssh?.password\n if (typeof reference === 'string') {\n for (const match of reference.matchAll(/\\$\\{([^:}]+)(?::[^}]*)?\\}/g))\n connectionVariables.add(match[1]!)\n }\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path: projectFile, line: '1' } }))\n }\n }\n const appEnv = Object.fromEntries(Object.entries(environment.data.values).filter(([key]) => key !== 'HAI_DEPLOY' && !connectionVariables.has(key) && !key.startsWith('HAI_CLI_') && (!key.startsWith('HAI_DEPLOY_') || key === 'HAI_DEPLOY_ENVIRONMENT')))\n const projectName = `${normalizeProjectName(scan.appName)}${scanOptions.environment ? `-${environment.data.environment}` : ''}`\n options = {\n ...options,\n ...(scanOptions.environment ? { environment: environment.data.environment } : {}),\n ...(options?.skipMiddleware ? { serviceModes: Object.fromEntries(scan.requiredServices.map(service => [service, 'keep' as const])) } : {}),\n }\n if (options.selectedServices) {\n options.serviceModes = {\n ...options.serviceModes,\n ...Object.fromEntries(scan.requiredServices.filter(service => !options.selectedServices!.includes(service)).map(service => [service, 'keep' as const])),\n }\n }\n\n // 容器 Provider(docker-ssh):走独立的容器部署编排\n if (currentContainerProvider) {\n return deployContainerApp(currentContainerProvider, appDir, scan, projectName, options, appEnv)\n }\n\n if (options?.bundleOnly)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleOnlyContainer'))\n if (options.selectedServices)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectedContainerOnly'))\n\n // 到此必为平台 Provider(vercel)\n if (!currentProvider) {\n return notInitialized.result()\n }\n\n // 2. 检查 adapter\n if (scan.isSvelteKit && !scan.adapterInstalled) {\n return err(\n HaiDeployError.ADAPTER_MISSING,\n deployM('deploy_adapterMissing', {\n params: { adapter: '@sveltejs/adapter-vercel' },\n }),\n )\n }\n\n if (!existsSync(resolveOutputDir(appDir, 'vercel')))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n\n // 3. 开通基础设施\n let allEnvVars: Record<string, string> = appEnv\n const recovery: DeployRecoveryInfo = { projectName, stage: 'provision', resources: [] }\n if (!options?.skipMiddleware) {\n const provResults = await deploy.provisionAll(projectName, options?.serviceModes ? scan.requiredServices.filter(service => usesDefaultMiddleware(scan, service, options)) : undefined)\n if (!provResults.success) {\n return err(provResults.error)\n }\n recovery.resources = provResults.data.map(({ envVars: _envVars, ...resource }) => resource)\n allEnvVars = { ...allEnvVars, ...mergeProvisionEnv(provResults.data, scan, options) }\n if (options?.environment) {\n const saved = saveDeploymentEnvironment(environment.data, mergeProvisionEnv(provResults.data, scan, options))\n if (!saved.success)\n return recoveryFailure(saved.error, { ...recovery, stage: 'save-env' })\n }\n }\n\n // 4. 创建平台项目\n const projectResult = await currentProvider.createProject(projectName)\n if (!projectResult.success) {\n return recoveryFailure(projectResult.error, { ...recovery, stage: 'create-project' })\n }\n const projectId = projectResult.data\n recovery.platformProjectId = projectId\n\n // 5. 设置环境变量\n if (Object.keys(allEnvVars).length > 0) {\n const envResult = await currentProvider.setEnvVars(projectId, allEnvVars)\n if (!envResult.success) {\n return recoveryFailure(envResult.error, { ...recovery, stage: 'set-env' })\n }\n }\n\n // 7. 部署\n const outputDir = resolveOutputDir(appDir, currentConfig?.provider.type ?? 'vercel')\n const deployResult = await currentProvider.deploy(projectId, outputDir)\n if (!deployResult.success) {\n return recoveryFailure(deployResult.error, { ...recovery, stage: 'deploy' })\n }\n\n // 补充环境变量列表到结果中\n const result: DeployResult = {\n ...deployResult.data,\n envVarsSet: Object.keys(allEnvVars),\n }\n\n logger.info('Deployment completed', {\n url: result.url,\n deploymentId: result.deploymentId,\n status: result.status,\n })\n\n return ok(result)\n },\n}\n\n/**\n * 容器 Provider(docker-ssh)部署编排。\n *\n * 校验 adapter-node → 开通云资源(可选)→ 交由容器 Provider 完成\n * 打包 / 传输 / compose up / 健康检查。\n *\n * @param provider - 容器部署 Provider\n * @param appDir - 应用根目录\n * @param scan - 扫描结果\n * @param rawProjectName - 原始项目名(未归一化)\n * @param options - 部署选项\n */\nasync function deployContainerApp(\n provider: ContainerDeployProvider,\n appDir: string,\n scan: ScanResult,\n rawProjectName: string,\n options?: DeployAppOptions,\n appEnv: Record<string, string> = {},\n): Promise<HaiResult<DeployResult>> {\n const projectName = normalizeProjectName(rawProjectName)\n\n let artifact\n let artifactDir = options?.artifactDir ?? resolveArtifactDirectory(appDir)\n try {\n if (existsSync(join(artifactDir, 'latest'))) {\n const latest = readFileSync(join(artifactDir, 'latest'), 'utf8').trim()\n if (!/^[a-z0-9][\\w.+-]*$/i.test(latest))\n throw new Error('Invalid artifact pointer')\n artifactDir = join(artifactDir, latest)\n }\n artifact = await readDeploymentArtifact(artifactDir)\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n }\n if (artifact.partial && !options?.selectedServices) {\n const selectedServices = artifact.images.map(image => image.name)\n options = {\n ...options,\n selectedServices,\n serviceModes: {\n ...options?.serviceModes,\n ...Object.fromEntries(scan.requiredServices.map(service => [service, 'keep' as const])),\n },\n }\n }\n if (!options?.bundleOnly && currentConfig?.provider.type === 'docker-ssh' && !currentConfig.provider.ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n\n let provisionEnv: Record<string, string> = {}\n if (!options?.skipMiddleware) {\n const provResults = await deploy.provisionAll(projectName, options?.serviceModes ? scan.requiredServices.filter(service => usesDefaultMiddleware(scan, service, options)) : undefined)\n if (!provResults.success) {\n return err(provResults.error)\n }\n provisionEnv = mergeProvisionEnv(provResults.data, scan, options)\n }\n\n return provider.deploy({ appDir, artifact, artifactDir, projectName, scan, provisionEnv, appEnv, options })\n}\n","/**\n * 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。\n * 字段名与对应模块公开 Schema 保持一致,不把模块依赖等同于必须创建外部服务。\n * @module deploy-middleware\n */\nimport type { ServiceType } from './deploy-types.js'\nimport { deployM } from './deploy-i18n.js'\n\n/**\n * 连接字段;例如 `{ name: 'port', defaultValue: '5432', kind: 'port' }`。\n * @example\n * ```ts\n * import type { MiddlewareField } from '@h-ai/deploy'\n * const field: MiddlewareField = { name: 'port', defaultValue: '5432', required: true, kind: 'port' }\n * ```\n */\nexport interface MiddlewareField {\n /** 模块配置字段名,camelCase 不拆词。 */\n name: string\n /** 无现有配置时使用的提示默认值。 */\n defaultValue?: string\n /** 是否为连接所必需;可选项允许留空。 */\n required?: boolean\n /** 密码输入与私有环境文件写入标记。 */\n secret?: boolean\n /** 交互校验类型;端口范围为 1–65535。 */\n kind?: 'port' | 'boolean' | 'number' | 'url'\n /** 数值下限;未声明时为 0。 */\n minimum?: number\n /** 数值上限;例如 Redis db 为 15。 */\n maximum?: number\n}\n\n/**\n * 后端目录项;例如 PostgreSQL 对应 `backend: 'postgresql'`。\n * @example\n * ```ts\n * import type { MiddlewareBackend } from '@h-ai/deploy'\n * const backend: MiddlewareBackend = { backend: 'postgresql', label: 'PostgreSQL', purpose: 'deploy_purposeDatabase', fields: [{ name: 'database', required: true }] }\n * ```\n */\nexport interface MiddlewareBackend {\n /** 模块 Schema 接受的后端标识。 */\n backend: string\n /** 可直接识别的产品名称。 */\n label: string\n /** 用途说明的 i18n 消息键。 */\n purpose: Parameters<typeof deployM>[0]\n /** 云自动开通器;缺失表示不能自动开通该云服务。 */\n provisioner?: 'neon' | 'upstash' | 'cloudflare-r2' | 'resend' | 'aliyun'\n /** 自定义连接需要逐项输入的字段。 */\n fields: MiddlewareField[]\n}\n\nconst field = (name: string, defaultValue?: string, kind?: MiddlewareField['kind'], secret = false): MiddlewareField => ({ name, defaultValue, kind, secret })\nconst required = (name: string, defaultValue?: string, kind?: MiddlewareField['kind']): MiddlewareField => ({ ...field(name, defaultValue, kind), required: true })\n\n/**\n * 所有可部署中间件的连接目录。\n * SQLite、memory、local 与 disabled 保留本地/禁用语义,不创建无关 sidecar。\n * 目录同时描述本机、禁用、自建与云后端;存在依赖不等于必须开通新资源。\n * @example\n * ```ts\n * import { DEPLOY_MIDDLEWARE, describeMiddlewareBackend } from '@h-ai/deploy'\n * const choices = DEPLOY_MIDDLEWARE.db.map(backend => ({ value: backend.backend, description: describeMiddlewareBackend(backend) }))\n * ```\n */\nexport const DEPLOY_MIDDLEWARE: Record<ServiceType, MiddlewareBackend[]> = {\n db: [\n { backend: 'sqlite', label: 'SQLite', purpose: 'deploy_purposeSqlite', fields: [required('database', './data/app.db')] },\n ...(['postgresql', 'mysql'] as const).map(backend => ({\n backend,\n label: backend === 'mysql' ? 'MySQL' : 'PostgreSQL',\n purpose: 'deploy_purposeDatabase' as const,\n provisioner: backend === 'postgresql' ? 'neon' as const : undefined,\n fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', backend === 'mysql' ? '3306' : '5432', 'port'), required('database', 'hai'), field('user', 'hai'), field('password', '', undefined, true), field('ssl', 'false')],\n })),\n ],\n cache: [\n { backend: 'memory', label: 'Memory', purpose: 'deploy_purposeMemory', fields: [] },\n { backend: 'redis', label: 'Redis', purpose: 'deploy_purposeCache', provisioner: 'upstash', fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', '6379', 'port'), field('password', '', undefined, true), { ...field('db', '0', 'number'), maximum: 15 }, field('tls', 'false', 'boolean'), field('keyPrefix'), field('connectTimeout', '10000', 'number'), field('commandTimeout', '5000', 'number')] },\n ],\n storage: [\n { backend: 'local', label: 'Local filesystem', purpose: 'deploy_purposeLocal', fields: [required('root', './data/storage')] },\n { backend: 's3', label: 'S3 / RustFS / MinIO / Cloudflare R2', purpose: 'deploy_purposeStorage', provisioner: 'cloudflare-r2', fields: [field('endpoint', '', 'url'), required('bucket', 'hai'), required('region', 'us-east-1'), required('accessKeyId'), { ...required('secretAccessKey'), secret: true }, field('forcePathStyle', 'true', 'boolean')] },\n ],\n vecdb: [\n { backend: 'lancedb', label: 'LanceDB', purpose: 'deploy_purposeLocal', fields: [required('path', './data/vectors')] },\n { backend: 'qdrant', label: 'Qdrant', purpose: 'deploy_purposeVector', fields: [required('url', 'http://localhost:6333', 'url'), field('apiKey', '', undefined, true)] },\n { backend: 'pgvector', label: 'PostgreSQL / pgvector', purpose: 'deploy_purposeVector', fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', '5432', 'port'), required('database', 'hai'), field('user', 'hai'), field('password', '', undefined, true)] },\n { backend: 'chroma', label: 'Chroma', purpose: 'deploy_purposeVector', fields: [required('url', 'http://localhost:8000', 'url')] },\n ],\n ldap: [\n { backend: 'disabled', label: 'Disabled', purpose: 'deploy_purposeDisabled', fields: [] },\n { backend: 'ldap', label: 'LDAP / OpenLDAP', purpose: 'deploy_purposeLdap', fields: [required('url', 'ldap://localhost:389', 'url'), required('bindDn', 'cn=admin,dc=example,dc=org'), { ...required('bindPassword'), secret: true }, required('searchBase', 'dc=example,dc=org'), field('searchFilter', '(uid={{username}})'), field('usernameAttribute', 'uid'), field('emailAttribute', 'mail'), field('displayNameAttribute', 'cn'), field('useTls', 'false', 'boolean'), { ...field('connectTimeout', '5000', 'number'), minimum: 1000 }] },\n ],\n email: [\n { backend: 'console', label: 'Console', purpose: 'deploy_purposeConsole', fields: [] },\n { backend: 'smtp', label: 'SMTP', purpose: 'deploy_purposeEmail', provisioner: 'resend', fields: [required('host', 'localhost'), required('port', '465', 'port'), field('secure', 'true', 'boolean'), field('user'), field('pass', '', undefined, true), required('from', 'noreply@example.com')] },\n { backend: 'api', label: 'HTTP notification API', purpose: 'deploy_purposeEmail', fields: [required('url', '', 'url'), field('method', 'POST'), field('headers'), field('timeout', '10000', 'number')] },\n ],\n sms: [\n { backend: 'console', label: 'Console', purpose: 'deploy_purposeConsole', fields: [] },\n { backend: 'aliyun-sms', label: 'Aliyun SMS', purpose: 'deploy_purposeSms', provisioner: 'aliyun', fields: [required('accessKeyId'), { ...required('accessKeySecret'), secret: true }, required('signName'), field('endpoint', 'dysmsapi.aliyuncs.com')] },\n { backend: 'api', label: 'HTTP notification API', purpose: 'deploy_purposeSms', fields: [required('url', '', 'url'), field('method', 'POST'), field('headers'), field('timeout', '10000', 'number')] },\n ],\n}\n\n/**\n * 返回当前语言的后端用途说明。\n * @param backend - 部署目录中的后端条目。\n * @returns 当前 locale 的用途说明。\n * @example\n * ```ts\n * import { DEPLOY_MIDDLEWARE, describeMiddlewareBackend } from '@h-ai/deploy'\n * const backend = DEPLOY_MIDDLEWARE.db.find(item => item.backend === 'postgresql')\n * if (backend) {\n * const description = describeMiddlewareBackend(backend)\n * }\n * ```\n */\nexport function describeMiddlewareBackend(backend: MiddlewareBackend): string {\n return deployM(backend.purpose)\n}\n","/** 只读部署预检;inspectRemote 仅通过 SSH 读取成功基线,不执行目标写入。 */\nimport type { DeployConfigInput } from './deploy-config.js'\nimport type { DeployAppOptions } from './deploy-types.js'\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { err, ok } from '@h-ai/core'\nimport { z } from 'zod'\nimport { planSidecars, resolveSidecarOptions } from './container/deploy-container-compose.js'\nimport { shellArgument } from './container/deploy-scripts.js'\nimport { createSshExecutor } from './container/deploy-ssh.js'\nimport { DeploymentArtifactSchema, readDeploymentArtifact } from './deploy-artifact.js'\nimport { DeployConfigSchema } from './deploy-config.js'\nimport { loadDeploymentEnvironment } from './deploy-environment.js'\nimport { normalizeProjectName, resolveArtifactDirectory, resolveProjectDirectory, usesDefaultMiddleware } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { scanApp } from './deploy-scanner.js'\nimport { HaiDeployError } from './deploy-types.js'\n\n/**\n * 查看与执行入口相同的扫描、环境、项目身份和制品校验结果。远端 current 只报告为待执行时核验。\n * 输出 root 是工程根,serviceDir 是读取运行配置、扫描依赖的部署服务目录。\n * @example\n * ```ts\n * import { createDeploymentPlan } from '@h-ai/deploy'\n * const plan = await createDeploymentPlan('/workspace/shop', { provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } }, { environment: 'prod' })\n * ```\n */\nexport async function createDeploymentPlan(appDir: string, input: DeployConfigInput, options: DeployAppOptions & { inspectRemote?: boolean } = {}) {\n if ('projectName' in options && options.projectName !== undefined)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameOverrideRemoved'))\n const parsed = DeployConfigSchema.safeParse(input)\n if (!parsed.success)\n return err({ ...HaiDeployError.CONFIG_ERROR, message: deployM('deploy_artifactInvalid'), ext: { fields: parsed.error.issues.map(issue => issue.path.join('.')) } })\n const config = parsed.data\n const scan = await scanApp(appDir, { environment: options.environment ?? config.environment, envDir: options.envDir })\n if (!scan.success)\n return scan\n const app = scan.data\n const directory = app.appDir ?? appDir\n const environment = await loadDeploymentEnvironment({ environment: options.environment ?? config.environment ?? 'prod', envDir: app.envDir ?? directory, requireFile: true })\n if (!environment.success)\n return environment\n const root = resolveProjectDirectory(directory)\n const projectName = normalizeProjectName(`${normalizeProjectName(app.appName)}${options.environment ?? config.environment ? `-${environment.data.environment}` : ''}`)\n const provider = config.provider\n try {\n let artifactDir = options.artifactDir ?? resolveArtifactDirectory(directory)\n if (existsSync(join(artifactDir, 'latest'))) {\n const latest = readFileSync(join(artifactDir, 'latest'), 'utf8').trim()\n if (!/^[a-z0-9][\\w.+-]*$/i.test(latest))\n throw new Error('Invalid pointer')\n artifactDir = join(artifactDir, latest)\n }\n const artifact = provider.type === 'docker-ssh' ? await readDeploymentArtifact(artifactDir) : undefined\n let images: string[]\n if (artifact) {\n images = [...new Set([artifact.primaryService, ...(artifact.hasWeb ? ['web'] : [])])]\n }\n else {\n // 平台部署没有 OCI 制品时,仍使用工程显式声明的角色,不能把静态或 SSR 站点改叫后端。\n const file = join(root, 'hai.json')\n const project = existsSync(file)\n ? z.object({ build: z.object({ images: z.array(z.object({ name: DeploymentArtifactSchema.shape.primaryService })).min(1).max(2).refine(items => new Set(items.map(item => item.name)).size === items.length).optional() }).optional() }).parse(JSON.parse(readFileSync(file, 'utf8')))\n : undefined\n images = project?.build?.images?.map(image => image.name) ?? [app.isSvelteKit ? 'web' : 'serv']\n }\n const middlewares = (app.middlewares ?? []).filter(item => !['sqlite', 'local', 'memory', 'disabled', 'console', 'lancedb'].includes(item.backend))\n const available = [...new Set([...images, ...app.requiredServices])]\n const selected = [...(options.selectedServices ?? (artifact?.partial ? artifact.images.map(image => image.name) : available))]\n if (!selected.length || new Set(selected).size !== selected.length || selected.some(name => !available.includes(name)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n if (artifact && selected.some(name => images.includes(name) && !artifact.images.some(image => image.name === name)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n const remoteDirectory = provider.type === 'docker-ssh' ? `${provider.remote.baseDir}/${projectName}` : undefined\n const baseline = { required: Boolean(artifact?.partial || options.selectedServices), state: 'not-inspected', current: remoteDirectory ? `${remoteDirectory}/current` : undefined, release: undefined as string | undefined }\n if (options.inspectRemote) {\n if (provider.type !== 'docker-ssh' || !provider.ssh || !remoteDirectory)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n // 仅读取 current 和成功发布目录;不能创建目录、锁、凭据或触发恢复。\n const command = `root=${shellArgument(remoteDirectory)}; if [ -f \"$root/current\" ]; then id=$(head -c 129 \"$root/current\"); case \"$id\" in ''|*[!a-zA-Z0-9._-]*) exit 2;; esac; test -f \"$root/releases/$id/compose-files\" || exit 3; printf '%s' \"$id\"; fi`\n const result = await createSshExecutor(provider.ssh).exec(command, { timeoutMs: 15000, maxCaptureChars: 1024 })\n if (!result.success) {\n baseline.state = 'unavailable'\n }\n else {\n const release = result.data.stdout.trim()\n if (release && !/^[\\w.-]{1,128}$/.test(release))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n baseline.state = release ? 'verified' : 'missing'\n baseline.release = release || undefined\n }\n }\n const configFiles = ['.env', '.env.local', `.env.${environment.data.environment}`, `.env.${environment.data.environment}.local`].map(name => join(environment.data.envDir, name)).filter(existsSync)\n const configDirectory = join(directory, 'config')\n if (existsSync(configDirectory))\n configFiles.push(...readdirSync(configDirectory, { withFileTypes: true }).filter(entry => entry.isFile() && /\\.ya?ml$/i.test(entry.name)).map(entry => join(configDirectory, entry.name)).sort())\n const serviceModes = { ...(options.skipMiddleware ? {} : options.serviceModes), ...Object.fromEntries(app.requiredServices.filter(service => options.skipMiddleware || !selected.includes(service)).map(service => [service, 'keep' as const])) }\n const effective = resolveSidecarOptions(app, { ...options, selectedServices: selected, serviceModes })\n // 只标记将由 Provisioner 提供的配置,不认证、不请求云资源,也不读取或创建本地凭据。\n const provisionKeys = { db: 'HAI_DB', cache: 'HAI_CACHE', storage: 'HAI_STORAGE', email: 'HAI_REACH_PROVIDERS', sms: 'HAI_REACH_PROVIDERS' } as const\n const provisionEnv: Record<string, string> = {}\n const provisioners = new Map<string, string>()\n for (const service of Object.keys(provisionKeys) as Array<keyof typeof provisionKeys>) {\n const provisioner = config.services?.[service]\n if (provisioner && !options.skipMiddleware && usesDefaultMiddleware(app, service, { ...options, serviceModes })) {\n provisionEnv[provisionKeys[service]] = 'planned'\n provisioners.set(service, provisioner.provisioner)\n }\n }\n const sidecar = provider.type === 'docker-ssh' ? planSidecars(directory, projectName, app, provisionEnv, effective, config.container?.s3Engine, { dbPassword: '', storagePassword: '', ldapPassword: '' }) : undefined\n const https = provider.type === 'docker-ssh' ? provider.expose.https : undefined\n const gateway = !!artifact && !(artifact.primaryService === 'serv' && artifact.hasWeb)\n && (sidecar?.services.includes('storage') || (!!https && (artifact.primaryService === 'serv' || app.isSvelteKit)))\n if (gateway && artifact.primaryService === 'web' && !app.isSvelteKit)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageBackendRequired'))\n if (gateway) {\n available.push('gateway')\n if (!baseline.required)\n selected.push('gateway')\n }\n if (https?.type === 'letsencrypt') {\n available.push('certbot')\n if (!baseline.required)\n selected.push('certbot')\n }\n const services = Object.entries(sidecar?.composeServices ?? {}).filter(([name]) => selected.includes(name))\n return ok({\n projectName,\n root,\n serviceDir: directory,\n environment: environment.data.environment,\n target: provider.type === 'docker-ssh' ? { provider: provider.type, host: provider.ssh?.host, port: provider.ssh?.port, directory: remoteDirectory, runtime: provider.remote.runtime, hostPort: provider.expose.hostPort, https: https ? { type: https.type, domain: https.domain, port: https.port } : undefined } : { provider: provider.type },\n artifact: artifact ? { directory: artifactDir, version: artifact.appVersion, buildId: artifact.buildId, verified: true, images: artifact.images.map(image => ({ name: image.name, reference: image.imageRef, sha256: image.sha256 })) } : undefined,\n selected,\n retained: available.filter(name => !selected.includes(name)),\n containers: provider.type === 'docker-ssh' ? [...selected.filter(name => images.includes(name) || name === 'gateway').map(name => `hai-${projectName}-${name}`), ...services.flatMap(([, service]) => typeof service.container_name === 'string' ? [service.container_name] : [])] : [],\n composeManagedServices: [...services.filter(([, service]) => typeof service.container_name !== 'string').map(([name]) => name), ...(selected.includes('certbot') ? ['certbot'] : [])],\n logicalVolumes: Object.keys(sidecar?.volumes ?? {}),\n middleware: middlewares.map(item => ({ service: item.service, backend: item.backend, configuration: item.envPrefix, action: selected.includes(item.service) ? effective.serviceModes?.[item.envPrefix] ?? effective.serviceModes?.[item.service] ?? 'default' : 'keep', provisioner: provisioners.get(item.service) })),\n configuration: { files: [join(root, 'hai.json'), ...configFiles].filter(existsSync), environmentKeys: Object.keys(environment.data.values).sort() },\n baseline,\n recovery: { releases: remoteDirectory ? `${remoteDirectory}/releases` : undefined, point: baseline.release ?? 'previous-successful-release', preservesVolumes: true, databaseRollback: false },\n })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n }\n}\n","/** 旧部署凭据的显式、只读预检与原子导入;不轮换密码、不变更容器和数据卷。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, lstatSync, readFileSync, realpathSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { err, ok } from '@h-ai/core'\nimport { z } from 'zod'\nimport { runCommand } from './container/deploy-command.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst nameSchema = z.string().regex(/^[a-z0-9][\\w.-]{0,127}$/i)\nconst passwordSchema = z.string().min(1).max(1024).refine(value => Buffer.from(value, 'utf8').toString('utf8') === value && [...value].every(character => character.codePointAt(0)! >= 32 && character.codePointAt(0) !== 127))\nconst importSchema = z.strictObject({\n version: z.literal(1),\n projectName: nameSchema,\n credentials: z.strictObject({ DB_PASSWORD: passwordSchema.optional(), STORAGE_PASSWORD: passwordSchema.optional(), LDAP_PASSWORD: passwordSchema.optional() }),\n services: z.array(z.strictObject({\n service: z.enum(['db', 'vecdb', 'storage', 'ldap']),\n container: nameSchema,\n kind: z.enum(['postgresql', 'mysql', 's3', 'ldap']),\n volumes: z.array(nameSchema).min(1).max(8),\n username: z.string().min(1).max(128).default('hai'),\n database: z.string().min(1).max(128).default('hai'),\n bucket: z.string().regex(/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/).default('hai'),\n accessKeyId: z.string().min(1).max(128).default('hai-storage'),\n region: z.string().regex(/^[a-z0-9-]+$/).default('us-east-1'),\n bindDn: z.string().min(1).max(512).default('cn=admin,dc=example,dc=org'),\n })).min(1).max(4),\n})\nconst groups = { db: 'DB_PASSWORD', vecdb: 'DB_PASSWORD', storage: 'STORAGE_PASSWORD', ldap: 'LDAP_PASSWORD' } as const\n\n/** 独立持锁进程只接受完整状态,原子发布并同步目录;中断时留下的私有 next 文件不被后续导入信任。 */\nconst importCommitScript = String.raw`(async()=>{const fs=require('node:fs'),path=require('node:path'),crypto=require('node:crypto');const root=process.argv[1];let temporary;\ntry{process.stdout.write('LOCKED\\n');let input='';for await(const chunk of process.stdin){input+=chunk;if(input.length>65536)throw Error()}\nif(!input)return;const {content}=JSON.parse(input);if(typeof content!=='string'||!content.startsWith('FORMAT_VERSION=2\\n'))throw Error();\nconst state=path.join(root,'managed-secrets.env');try{fs.lstatSync(state);throw Error('exists')}catch(error){if(error.code!=='ENOENT')throw error}\ntemporary=path.join(root,'.managed-secrets-'+crypto.randomUUID()+'.next');const fd=fs.openSync(temporary,fs.constants.O_WRONLY|fs.constants.O_CREAT|fs.constants.O_EXCL|fs.constants.O_NOFOLLOW,0o600);\ntry{fs.writeFileSync(fd,content);fs.fsyncSync(fd)}finally{fs.closeSync(fd)}fs.renameSync(temporary,state);temporary=undefined;\nconst directory=fs.openSync(root,fs.constants.O_RDONLY);try{fs.fsyncSync(directory)}finally{fs.closeSync(directory)}process.stdout.write('COMMITTED\\n');\n}catch{process.exitCode=1}finally{if(temporary)try{fs.unlinkSync(temporary)}catch{}}})()`\n\n/** 仅在同项目的现有 Node 应用容器中执行 S3 HEAD;不写配置,不跟随重定向,不输出服务响应。 */\nconst s3VerificationScript = String.raw`(async()=>{try{\nconst {createHash,createHmac}=require('node:crypto');let input='';for await(const chunk of process.stdin)input+=chunk;\nconst {endpoint,bucket,accessKeyId,secret,region}=JSON.parse(input);const url=new URL('/'+encodeURIComponent(bucket),endpoint);\nconst hash=value=>createHash('sha256').update(value).digest('hex');const hmac=(key,value)=>createHmac('sha256',key).update(value).digest();\nconst date=new Date().toISOString().replace(/[:-]|\\.\\d{3}/g,'');const day=date.slice(0,8);const payload=hash('');\nconst headers='host:'+url.host+'\\nx-amz-content-sha256:'+payload+'\\nx-amz-date:'+date+'\\n';const signed='host;x-amz-content-sha256;x-amz-date';\nconst scope=day+'/'+region+'/s3/aws4_request';const canonical=['HEAD',url.pathname,'',headers,signed,payload].join('\\n');\nconst key=hmac(hmac(hmac(hmac('AWS4'+secret,day),region),'s3'),'aws4_request');const signature=hmac(key,['AWS4-HMAC-SHA256',date,scope,hash(canonical)].join('\\n')).toString('hex');\nconst response=await fetch(url,{method:'HEAD',redirect:'manual',signal:AbortSignal.timeout(10000),headers:{'x-amz-date':date,'x-amz-content-sha256':payload,Authorization:'AWS4-HMAC-SHA256 Credential='+accessKeyId+'/'+scope+', SignedHeaders='+signed+', Signature='+signature}});\nawait response.body?.cancel();if(response.ok)process.stdout.write('VERIFIED');else process.exitCode=1;\n}catch{process.exitCode=1}})()`\n\n/**\n * 在目标服务器导入前核验旧凭据;dryRun 默认 true,apply 需要 Linux flock 与运行中的原服务。\n * 输入文件必须由操作者明确指定,权限 0600;API 不读取旧部署包猜测密码。\n * @param options - 服务器项目目录、受保护的导入 JSON、容器引擎和只读开关。\n * @param options.directory - 目标 Linux 服务器上已存在的项目部署目录。\n * @param options.inputFile - 操作者提供的版本化私有 JSON 文件路径。\n * @param options.runtime - 实际使用的 Docker 或 Podman 引擎。\n * @param options.dryRun - 默认 true;只有显式 false 才在部署锁内保存状态。\n * @returns 仅包含项目、凭据组和卷名的回执,不包含密码;失败不推进 current 或改变服务。\n * @example\n * ```ts\n * import { importDeploymentSecrets } from '@h-ai/deploy'\n * const plan = await importDeploymentSecrets({ directory: '/opt/hai/apps/shop-test', inputFile: '/private/shop-import.json', runtime: 'docker' })\n * if (!plan.success) throw new Error(plan.error.message)\n * // 停止业务写入、备份数据后,用相同输入显式传 dryRun: false 导入。\n * ```\n */\nexport async function importDeploymentSecrets(options: {\n directory: string\n inputFile: string\n runtime: 'docker' | 'podman'\n dryRun?: boolean\n}): Promise<HaiResult<{ projectName: string, stateVersion: 2, groups: string[], volumes: string[], changed: boolean }>> {\n let lock: Awaited<ReturnType<typeof acquireImportLock>> | undefined\n let commitAttempted = false\n let phase: 'input' | 'identity' | 'verification' | 'lock' | 'state' = 'input'\n try {\n if (!['docker', 'podman'].includes(options.runtime))\n throw new Error('input')\n const root = resolve(options.directory)\n if (realpathSync(root) !== root || !lstatSync(root).isDirectory() || (process.platform !== 'win32' && (lstatSync(root).mode & 0o022)))\n throw new Error('input')\n const input = privateFile(resolve(options.inputFile))\n const parsed = importSchema.safeParse(JSON.parse(input))\n if (!parsed.success)\n return err({ ...HaiDeployError.CONFIG_ERROR, message: deployM('deploy_secretImportFailed', { params: { phase } }), ext: { phase, state: 'unchanged', fields: parsed.error.issues.map(issue => issue.path.join('.')) } })\n const config = parsed.data\n const project = `hai-${config.projectName}`\n const selectedGroups = [...new Set(config.services.map(service => groups[service.service]))].sort()\n if (new Set(config.services.map(service => service.service)).size !== config.services.length\n || Object.keys(config.credentials).some(group => !selectedGroups.includes(group as typeof selectedGroups[number]))\n || selectedGroups.some(group => !config.credentials[group])) {\n throw new Error('input')\n }\n const secrets = Object.values(config.credentials).filter((value): value is string => typeof value === 'string')\n const stateFile = join(root, 'managed-secrets.env')\n const lockFile = join(root, '.deploy.lock')\n phase = 'lock'\n if (options.dryRun === false) {\n if (process.platform !== 'linux')\n throw new Error('lock')\n if (existsSync(lockFile) && (lstatSync(lockFile).isSymbolicLink() || !lstatSync(lockFile).isFile() || lstatSync(lockFile).nlink !== 1))\n throw new Error('lock')\n lock = await acquireImportLock(lockFile, root)\n }\n phase = 'identity'\n const volumes: Array<{ group: string, name: string }> = []\n for (const service of config.services) {\n const kindValid = service.service === 'storage' ? service.kind === 's3' : service.service === 'ldap' ? service.kind === 'ldap' : ['postgresql', 'mysql'].includes(service.kind)\n if (!kindValid)\n throw new Error('identity')\n // 受管 sidecar 固定账户/库/桶身份;不能只导入密码后让后续部署悄悄切换身份。\n if ((['postgresql', 'mysql'].includes(service.kind) && (service.username !== 'hai' || service.database !== 'hai'))\n || (service.kind === 's3' && (service.accessKeyId !== 'hai-storage' || service.bucket !== 'hai' || service.region !== 'us-east-1'))\n || (service.kind === 'ldap' && service.bindDn !== 'cn=admin,dc=example,dc=org')) {\n throw new Error('identity')\n }\n const identity = await inspectContainer(options.runtime, service.container, secrets)\n if (identity.project !== project || identity.service !== service.service || !identity.running)\n throw new Error('identity')\n for (const volume of service.volumes) {\n if (!identity.volumes.includes(volume))\n throw new Error('identity')\n volumes.push({ group: groups[service.service], name: volume })\n }\n phase = 'verification'\n const password = config.credentials[groups[service.service]]!\n let verified = false\n if (service.kind === 's3') {\n const helper = `hai-${config.projectName}-app`\n const application = await inspectContainer(options.runtime, helper, secrets)\n if (application.project !== project || application.service !== 'app' || !application.running || !application.networks.some(network => identity.networks.includes(network)))\n throw new Error('identity')\n const result = await runCommand(options.runtime, ['exec', '-i', helper, 'node', '-e', s3VerificationScript], { input: JSON.stringify({ endpoint: `http://${service.container}:9000`, bucket: service.bucket, accessKeyId: service.accessKeyId, secret: password, region: service.region }), secrets, timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = result.success && result.data.stdout.trim() === 'VERIFIED'\n }\n else {\n const args = service.kind === 'ldap'\n ? ['exec', '-i', service.container, 'ldapwhoami', '-x', '-H', 'ldap://127.0.0.1:389', '-D', service.bindDn, '-y', '/dev/stdin']\n : ['exec', '-i', service.container, 'sh', '-c', service.kind === 'postgresql'\n ? 'IFS= read -r PGPASSWORD; export PGPASSWORD; exec psql --no-psqlrc -h \"$3\" -U \"$1\" -d \"dbname=$2 require_auth=scram-sha-256,md5,password\" -Atc \"SELECT 1\"'\n : 'IFS= read -r MYSQL_PWD; export MYSQL_PWD; exec mysql -h 127.0.0.1 -u \"$1\" \"$2\" -Nse \"SELECT 1\"', 'hai-secret-check', service.username, service.database, service.container]\n // LDAP -y 按文件字节读取密码,不能附加 shell read 使用的行尾。\n const result = await runCommand(options.runtime, args, { input: service.kind === 'ldap' ? password : `${password}\\n`, secrets, timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = result.success && !result.data.stdoutTruncated && (service.kind === 'ldap' ? result.data.stdout.trim().startsWith('dn:') : result.data.stdout.trim() === '1')\n if (verified && service.kind === 'mysql') {\n const rootCheck = await runCommand(options.runtime, [...args.slice(0, -3), 'root', service.database, service.container], { input: `${password}\\n`, secrets, timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = rootCheck.success && !rootCheck.data.stdoutTruncated && rootCheck.data.stdout.trim() === '1'\n // MySQL 的各版本不统一暴露 skip_grant_tables;实际错误密码必须收到认证拒绝。\n const invalidPassword = `hai-import-invalid-${randomUUID()}`\n for (const username of [service.username, 'root']) {\n if (!verified)\n break\n const negative = await runCommand(options.runtime, [...args.slice(0, -3), username, service.database, service.container], { input: `${invalidPassword}\\n`, secrets: [...secrets, invalidPassword], timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = !negative.success && /ERROR 1045 \\(28000\\)/.test(negative.error.message)\n }\n }\n }\n if (!verified)\n throw new Error('verification')\n phase = 'identity'\n }\n phase = 'state'\n const uniqueVolumes = [...new Map(volumes.map(volume => [`${volume.group}:${volume.name}`, volume])).values()].sort((a, b) => `${a.group}:${a.name}`.localeCompare(`${b.group}:${b.name}`))\n const lines = ['FORMAT_VERSION=2', `PROJECT=${project}`, ...selectedGroups.map(group => `${group}=${Buffer.from(config.credentials[group]!, 'utf8').toString('hex')}`), ...uniqueVolumes.map((volume, index) => `VOLUME_${index + 1}=${volume.group}:${volume.name}`)]\n let changed = false\n if (existsSync(stateFile) || isSymbolicLink(stateFile)) {\n const existing = readImportedState(privateFile(stateFile))\n if (existing.FORMAT_VERSION !== '2' || existing.PROJECT !== project || selectedGroups.some(group => existing[group] !== Buffer.from(config.credentials[group]!, 'utf8').toString('hex')) || uniqueVolumes.some(volume => !Object.entries(existing).some(([key, value]) => /^VOLUME_\\d+$/.test(key) && value === `${volume.group}:${volume.name}`)))\n throw new Error('state')\n }\n else if (options.dryRun === false) {\n commitAttempted = true\n if (!lock || !await lock.commit(`${lines.join('\\n')}\\n`))\n throw new Error('lock')\n changed = true\n }\n return ok({ projectName: config.projectName, stateVersion: 2, groups: selectedGroups, volumes: uniqueVolumes.map(volume => volume.name), changed })\n }\n catch {\n return err({ ...HaiDeployError.CONFIG_ERROR, message: deployM('deploy_secretImportFailed', { params: { phase } }), ext: { phase, state: commitAttempted ? 'unknown' : 'unchanged' } })\n }\n finally {\n await lock?.release()\n }\n}\n\nfunction readImportedState(text: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of text.trimEnd().split('\\n')) {\n const match = /^(FORMAT_VERSION|PROJECT|DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD|VOLUME_[1-9]\\d*)=([^=]+)$/.exec(line)\n if (!match || Object.hasOwn(result, match[1]!))\n throw new Error('state')\n const key = match[1]!\n const value = match[2]!\n if (key.endsWith('_PASSWORD')) {\n if (!/^(?:[a-f0-9]{2})+$/.test(value))\n throw new Error('state')\n const decoded = Buffer.from(value, 'hex').toString('utf8')\n if (!passwordSchema.safeParse(decoded).success || Buffer.from(decoded, 'utf8').toString('hex') !== value)\n throw new Error('state')\n }\n else if (key.startsWith('VOLUME_') && !/^(?:DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD):[a-zA-Z0-9][\\w.-]*$/.test(value)) {\n throw new Error('state')\n }\n result[key] = value\n }\n if (result.FORMAT_VERSION !== '2' || !nameSchema.safeParse(result.PROJECT).success)\n throw new Error('state')\n return result\n}\n\nfunction isSymbolicLink(path: string): boolean {\n try {\n return lstatSync(path).isSymbolicLink()\n }\n catch {\n return false\n }\n}\n\nfunction privateFile(path: string): string {\n const stat = lstatSync(path)\n if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1 || stat.size > 65536 || (process.platform !== 'win32' && ((stat.mode & 0o077) || (process.getuid?.() !== 0 && stat.uid !== process.getuid?.()))))\n throw new Error('private-file')\n return readFileSync(path, 'utf8')\n}\n\nasync function inspectContainer(runtime: string, container: string, secrets: string[]) {\n const result = await runCommand(runtime, ['inspect', '--format', '{{json .Config.Labels}}\\n{{json .Mounts}}\\n{{json .State.Running}}\\n{{json .NetworkSettings.Networks}}', container], { secrets, timeoutMs: 10000, maxCaptureChars: 32768 })\n if (!result.success || result.data.stdoutTruncated)\n throw new Error('identity')\n const [labelsText, mountsText, runningText, networksText] = result.data.stdout.trim().split('\\n')\n const labels = z.record(z.string(), z.string()).parse(JSON.parse(labelsText!))\n const mounts = z.array(z.object({ Type: z.string(), Name: z.string().optional() })).parse(JSON.parse(mountsText!))\n // Podman 的默认 pasta/slirp 网络可返回 null;原生 DB/LDAP 验证不要求命名网络。\n const networks = z.record(z.string(), z.object({ NetworkID: z.string() })).parse(JSON.parse(networksText!) ?? {})\n // 每种已声明的标准标签必须完整,两个命名空间同时声明时保持一致,禁止混拼身份。\n const dockerProject = labels['com.docker.compose.project'] || undefined\n const podmanProject = labels['io.podman.compose.project'] || undefined\n const dockerService = labels['com.docker.compose.service'] || undefined\n const podmanService = labels['io.podman.compose.service'] || undefined\n if (Boolean(dockerProject) !== Boolean(dockerService) || Boolean(podmanProject) !== Boolean(podmanService)\n || (dockerProject && podmanProject && dockerProject !== podmanProject) || (dockerService && podmanService && dockerService !== podmanService)) {\n throw new Error('identity')\n }\n return { project: dockerProject ?? podmanProject, service: dockerService ?? podmanService, running: runningText === 'true', volumes: mounts.flatMap(mount => mount.Type === 'volume' && mount.Name ? [mount.Name] : []), networks: Object.values(networks).map(network => network.NetworkID) }\n}\n\n/** flock 子进程持有同一个固定锁文件;父进程消失后 stdin 关闭,自然释放锁。 */\nasync function acquireImportLock(path: string, root: string): Promise<{ commit: (content: string) => Promise<boolean>, release: () => Promise<void> }> {\n return new Promise((resolveLock, reject) => {\n // 最终写入也由持锁进程完成;锁 helper 意外退出时父进程无法越过锁提交。\n const child = spawn('flock', ['-n', path, process.execPath, '-e', importCommitScript, root], { stdio: ['pipe', 'pipe', 'ignore'], windowsHide: true })\n let acquired = false\n let exited = false\n let output = ''\n const finished = new Promise<void>(done => child.once('close', () => {\n exited = true\n done()\n }))\n child.stdin.on('error', () => { /* 由提交回执判断失败,不泄漏输入。 */ })\n const timer = setTimeout(() => {\n child.stdin.end()\n child.kill()\n reject(new Error('lock'))\n }, 5000)\n child.once('error', () => {\n clearTimeout(timer)\n reject(new Error('lock'))\n })\n child.once('exit', () => {\n if (!acquired) {\n clearTimeout(timer)\n reject(new Error('lock'))\n }\n })\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString()\n if (acquired || !output.includes('\\n'))\n return\n if (!output.startsWith('LOCKED\\n') || exited) {\n child.stdin.end()\n reject(new Error('lock'))\n return\n }\n acquired = true\n clearTimeout(timer)\n resolveLock({\n commit: async (content) => {\n if (exited)\n return false\n child.stdin.end(JSON.stringify({ content }))\n await finished\n return child.exitCode === 0 && output === 'LOCKED\\nCOMMITTED\\n'\n },\n release: async () => {\n child.stdin.end()\n await finished\n },\n })\n })\n })\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/deploy-artifact.ts","../messages/en-US.json","../messages/ja-JP.json","../messages/zh-CN.json","../src/deploy-i18n.ts","../src/deploy-config.ts","../src/deploy-types.ts","../src/deploy-environment.ts","../src/deploy-functions.ts","../src/deploy-credentials.ts","../src/deploy-middleware-config.ts","../src/deploy-recovery.ts","../src/deploy-scanner.ts","../src/container/deploy-compose-identity.ts","../src/container/deploy-managed-secrets.ts","../src/container/deploy-backend-state.ts","../src/container/deploy-command-windows.ts","../src/container/deploy-command-process.ts","../src/container/deploy-secret-masker.ts","../src/container/deploy-command.ts","../src/container/deploy-ssh-askpass.ts","../src/container/deploy-target.ts","../src/container/deploy-scripts.ts","../src/container/deploy-ssh.ts","../src/container/deploy-bundle.ts","../src/container/deploy-https.ts","../src/container/deploy-container-compose.ts","../src/providers/deploy-provider-docker-ssh.ts","../src/providers/deploy-provider-vercel.ts","../src/provisioners/deploy-provisioner-aliyun.ts","../src/provisioners/deploy-provisioner-neon.ts","../src/provisioners/deploy-provisioner-r2.ts","../src/provisioners/deploy-provisioner-resend.ts","../src/provisioners/deploy-provisioner-upstash.ts","../src/deploy-main.ts","../src/deploy-middleware.ts","../src/deploy-plan.ts","../src/deploy-secrets.ts"],"names":["z","core","field","existsSync","readFileSync","process","resolve","privateFile","join","dirname","parse","writeFileSync","ok","err","logger","parseEnv","key","setTimeout","lstatSync","chmodSync","helper","basename","mkdtempSync","mkdirSync","createHash","rmSync","createReadStream","stringify","randomBytes","request","requestHttps","deploy","name","prepared","resolveTransportBodyLimits","relative","statSync","connectionUri","Buffer","readdirSync","groups","realpathSync","randomUUID","spawn"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAqOhB;AC5RA,IAAM,YAAY,MAAA,CAAO,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,C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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","file":"index.js","sourcesContent":["/** 已构建镜像的交付契约;构建器写入,部署器只校验和消费。 */\nimport { createHash } from 'node:crypto'\nimport { createReadStream, existsSync, lstatSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { z } from 'zod'\n\n/**\n * 镜像制品清单,例如 `{ version: 4, primaryService: 'serv', appVersion: '1.2.3', buildId: '1.2.3-build1', partial: false, hasWeb: false, images: [...] }`。\n * 根目录制品保留格式4;非根目录使用格式5,强制旧部署器拒绝而非静默忽略挂载路径。\n * 完整产物包含primaryService,hasWeb记录浏览器端拓扑;结构验证不能代替真实归档校验。\n * @example\n * ```ts\n * import { readFile } from 'node:fs/promises'\n * import { DeploymentArtifactSchema } from '@h-ai/deploy'\n * const content = await readFile('.hai/build/docker/build-id/manifest.json', 'utf8')\n * const parsed = DeploymentArtifactSchema.safeParse(JSON.parse(content))\n * if (!parsed.success) throw new Error('Invalid artifact manifest')\n * // Schema 只验证结构;文件路径与 SHA-256 核验使用 readDeploymentArtifact。\n * ```\n */\nexport const DeploymentArtifactSchema = z.object({\n /** 清单格式版本,与应用版本和部署环境无关。 */\n version: z.union([z.literal(4), z.literal(5)]),\n /** 主运行服务:独立后端为 serv,独立浏览器站点(静态或 SSR)为 web。 */\n primaryService: z.enum(['serv', 'web']),\n /** 应用根 package.json 的版本,用于归档、Compose 与桌面交付;最长 80 字符。 */\n appVersion: z.string().max(80).regex(/^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9a-z-]+(?:\\.[0-9a-z-]+)*)?(?:\\+[0-9a-z-]+(?:\\.[0-9a-z-]+)*)?$/i),\n /** 本次构建标识;同一应用版本允许重复构建。 */\n buildId: z.string().max(128).regex(/^[a-z0-9][\\w.+-]*$/i),\n /** 只包含所选镜像的构建不能用于首次安装。 */\n partial: z.boolean().default(false),\n /** 是否包含浏览器端;仅构建 serv 时也保留完整工程的 Web 拓扑。 */\n hasWeb: z.boolean().default(false),\n /** Web构建的公开挂载目录,无末尾斜杠;省略或空字符串保持域名根目录。增量制品须保留完整拓扑的同一值。 */\n webBasePath: z.string().refine(value => value === '' || (/^\\/[\\w.-]+(?:\\/[\\w.-]+)*$/.test(value) && !value.split('/').some(segment => segment === '.' || segment === '..'))).optional(),\n /** 工程显式配置的后端端口,部分构建未包含 serv 时仍保留。 */\n servContainerPort: z.number().int().min(1).max(65535).optional(),\n /** 工程显式配置的 Web 端口,部分构建未包含 web 镜像时仍保留;缺省使用部署默认值。 */\n webContainerPort: z.number().int().min(1).max(65535).optional(),\n /** 本次构建选择的镜像归档。 */\n images: z.array(z.object({\n /** serv 为独立 API 后端,web 为浏览器站点(静态或 SSR)。 */\n name: z.enum(['serv', 'web']),\n /** 相对于清单目录的 tar 文件名。 */\n file: z.string().regex(/^[\\w.+-]+\\.tar$/),\n /** 归档导入后可直接使用的不可变镜像引用。 */\n imageRef: z.string().regex(/^[a-z0-9][a-z0-9./:_-]*:[a-z0-9_][a-z0-9_.-]*$/).refine(value => !value.endsWith(':latest')),\n /** tar 内容的 SHA-256,用于部署前校验。 */\n sha256: z.string().regex(/^[a-f0-9]{64}$/),\n /** 容器内部监听端口;服务器公开端口由部署选择。 */\n containerPort: z.number().int().min(1).max(65535).optional(),\n })).min(1).max(2).refine(images => new Set(images.map(image => image.name)).size === images.length),\n}).refine(artifact => artifact.version === 5 ? !!artifact.webBasePath : !artifact.webBasePath).refine(artifact => !artifact.webBasePath || artifact.hasWeb).refine(artifact => artifact.images.every(image => image.file === `${image.name}-${artifact.appVersion}.tar`)).refine(artifact => artifact.primaryService !== 'web' || artifact.hasWeb).refine(artifact => artifact.images.every(image => image.name === artifact.primaryService || (image.name === 'web' && artifact.hasWeb))).refine(artifact => artifact.partial || artifact.images.some(image => image.name === artifact.primaryService)).refine(artifact => artifact.partial || !artifact.hasWeb || artifact.images.some(image => image.name === 'web'))\n\n/**\n * 构建器与部署器共享的镜像交付结构;参见 DeploymentArtifactSchema 示例。\n * @example\n * ```ts\n * import type { DeploymentArtifact } from '@h-ai/deploy'\n * import { readDeploymentArtifact } from '@h-ai/deploy'\n * const directory = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(directory)\n * const verified: DeploymentArtifact = artifact\n * const references = verified.images.map(image => image.imageRef)\n * ```\n */\nexport type DeploymentArtifact = z.infer<typeof DeploymentArtifactSchema>\n\n/**\n * 流式计算制品校验和,避免将大镜像一次性读入内存。\n * @throws Error - 文件读取失败;返回真实 tar 内容的 SHA-256,不校验清单其它字段。\n * @param file - 真实镜像归档文件路径。\n * @returns 文件内容的 SHA-256 十六进制摘要。\n * @example\n * ```ts\n * import { artifactChecksum } from '@h-ai/deploy'\n * const digest = await artifactChecksum('.hai/build/docker/build-id/serv-1.0.0.tar')\n * ```\n */\nexport async function artifactChecksum(file: string): Promise<string> {\n const hash = createHash('sha256')\n for await (const chunk of createReadStream(file))\n hash.update(chunk)\n return hash.digest('hex')\n}\n\n/**\n * 校验完整构建产物;缺失、损坏或非法清单均抛错,由部署边界转换为 HaiResult。\n * @throws Error - 清单、路径、镜像 tar 或摘要校验失败;不能用未验证的清单绕过本函数。\n * @param directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @returns 已经验证的构建制品清单。\n * @example\n * ```ts\n * import { readDeploymentArtifact } from '@h-ai/deploy'\n * const directory = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(directory)\n * const images = artifact.images.map(image => ({ name: image.name, imageRef: image.imageRef }))\n * ```\n */\nexport async function readDeploymentArtifact(directory: string): Promise<DeploymentArtifact> {\n const artifact = DeploymentArtifactSchema.parse(JSON.parse(readFileSync(resolve(directory, 'manifest.json'), 'utf8')))\n for (const image of artifact.images) {\n const file = resolve(directory, image.file)\n if (!existsSync(file) || !lstatSync(file).isFile() || lstatSync(file).isSymbolicLink() || await artifactChecksum(file) !== image.sha256)\n throw new Error(`Invalid artifact: ${image.file}`)\n }\n return artifact\n}\n","{\n \"deploy_notInitialized\": \"Deploy module not initialized, call deploy.init() first\",\n \"deploy_initFailed\": \"Deploy module initialization failed: {error}\",\n \"deploy_unsupportedProviderType\": \"Unsupported deploy provider type: {type}\",\n \"deploy_unsupportedProvisionerType\": \"Unsupported service provisioner type: {type}\",\n \"deploy_configTokenRequired\": \"Deploy provider token is required\",\n \"deploy_authRequired\": \"Authentication required\",\n \"deploy_authFailed\": \"Authentication failed: {error}\",\n \"deploy_projectCreateFailed\": \"Project creation failed: {error}\",\n \"deploy_uploadFailed\": \"Build output upload failed: {error}\",\n \"deploy_deployFailed\": \"Deployment failed: {error}\",\n \"deploy_provisionFailed\": \"Service provisioning failed: {service} - {error}\",\n \"deploy_adapterMissing\": \"Target platform adapter not found, please install {adapter}\",\n \"deploy_scanFailed\": \"Application scan failed: {error}\",\n \"deploy_envVarFailed\": \"Environment variable setup failed: {error}\",\n \"deploy_credentialError\": \"Credential read/write failed: {error}\",\n \"deploy_credentialInvalidKey\": \"Unsupported credential key: {key}. Only HAI_DEPLOY_* keys are allowed\",\n \"deploy_credentialSaved\": \"Credentials saved\",\n \"deploy_credentialLoaded\": \"Credentials loaded\",\n \"deploy_configError\": \"Deploy config error: {error}\",\n \"deploy_credentialMissing\": \"Missing credential fields: {fields}\",\n \"deploy_apiError\": \"{service} API error ({status})\",\n \"deploy_fileUploadFailed\": \"File upload failed ({status})\",\n \"deploy_provisionNoResult\": \"No connection info returned from {service}\",\n \"deploy_recoveryFailure\": \"Deployment stopped at {stage}; inspect the recovery details.\",\n \"deploy_recoverySuggestion\": \"Inspect listed resources in the provider console before retrying with the same project name. Unknown means the request may have created a resource. Reused resources are never deleted automatically; remove newly created resources manually only after checking their use.\",\n \"deploy_commandTimeout\": \"Command timed out: {command}\",\n \"deploy_commandFailed\": \"Command failed ({command}): {error}\",\n \"deploy_remoteConnectFailed\": \"Cannot connect to remote host {host}: {error}\",\n \"deploy_remoteRuntimeMissing\": \"Remote host missing container runtime or compose: {runtime}\",\n \"deploy_imageTransferFailed\": \"Image transfer failed: {error}\",\n \"deploy_healthCheckFailed\": \"Health check failed, app not ready at {url}\",\n \"deploy_invalidEnvironment\": \"Use letters, numbers, underscores or hyphens for the environment; local/example are reserved.\",\n \"deploy_environmentMissing\": \"Environment file missing: {path}. Create and configure it before deploying.\",\n \"deploy_environmentReadFailed\": \"Cannot read deployment environment files; check syntax and permissions.\",\n \"deploy_environmentWriteFailed\": \"Cannot save deployment configuration; check file syntax and permissions.\",\n \"deploy_multipleApplications\": \"Multiple service packages found; specify the application directory.\",\n \"deploy_purposeSqlite\": \"Local relational database persisted in a volume\",\n \"deploy_purposeDatabase\": \"Relational database service for business data\",\n \"deploy_purposeMemory\": \"Per-process memory cache; cleared on restart, no external service\",\n \"deploy_purposeLocal\": \"Local filesystem storage persisted in a volume\",\n \"deploy_purposeCache\": \"Shared cache, sessions and distributed locks\",\n \"deploy_purposeStorage\": \"S3-compatible object storage for uploaded files\",\n \"deploy_purposeVector\": \"Vector indexing and similarity search\",\n \"deploy_purposeDisabled\": \"LDAP login is disabled; no directory service is created\",\n \"deploy_purposeLdap\": \"Directory account authentication; the default directory has no business users\",\n \"deploy_purposeConsole\": \"Messages go to application logs without delivery\",\n \"deploy_purposeEmail\": \"Email/HTTP delivery; the default SMTP container only captures test messages\",\n \"deploy_purposeSms\": \"SMS through Aliyun credentials; requires an existing signature and quota\",\n \"deploy_webProxyInvalid\": \"The API prefix must be an absolute path containing only letters, numbers, underscores, hyphens and slashes.\",\n \"deploy_webBaseConflict\": \"The website mount path conflicts with an API or health endpoint. Choose a different PUBLIC_BASE_PATH.\",\n \"deploy_storageProxyInvalid\": \"Cannot generate the storage proxy. Use a valid DNS bucket name whose path does not overlap the website, API, or health endpoints.\",\n \"deploy_storagePublicEndpointInvalid\": \"Invalid storage.publicEndpoint. Use a browser-accessible HTTP(S) address with an optional valid proxy path, without a bucket, credentials, query or fragment.\",\n \"deploy_storageBackendRequired\": \"A static browser app cannot deploy server-side storage credentials. Configure Storage in Serv or SvelteKit and obtain presigned links through its API.\",\n \"deploy_artifactInvalid\": \"Image artifacts are missing or invalid. Run pnpm build --target image, select valid --artifact-dir, or use pnpm run deploy --build.\",\n \"deploy_sshRequired\": \"Automatic deployment requires SSH settings. Use --bundle-only for manual transfer when the server is unreachable.\",\n \"deploy_sshPasswordInvalid\": \"SSH passwords must be nonempty, contain no CR/LF/NUL, and be at most 1023 UTF-8 bytes.\",\n \"deploy_sshAskpassFailed\": \"Could not prepare the managed SSH password helper. Check OpenSSH and Windows PowerShell 5.\",\n \"deploy_sshAskpassCleanupFailed\": \"Could not confirm cleanup of this SSH password helper. Inspect the local temporary directory.\",\n \"deploy_targetAuth\": \"Authentication: key uses a private key or ssh-agent; password reads the local environment variable named by passwordEnv.\",\n \"deploy_targetPasswordEnv\": \"Environment variable name only, never the password. Reuse the operator environment; if missing, the uploader prompts for hidden input for this run only. Defaults to HAI_DEPLOY_PROVIDER_SSH_PASSWORD.\",\n \"deploy_bundleInstructions\": \"Bundle: {file}\\nIncludes all images needed by selected services, including self-hosted middleware.\\nWith SSH access, first edit deploy-target.json in the same delivery directory using its _comments, then run deploy.ps1 (Windows) or deploy.sh (Linux/macOS) there. Both read this JSON; the sh entry also requires local awk.\\nFor isolated servers, copy the entire delivery directory to Linux and run sh deploy-local.sh there. It extracts the archive, applies it and preserves logs. An optional first argument overrides the server deployment directory.\\nLinux requires Docker/Podman, Compose, sh, tar, sha256sum, awk, curl, util-linux flock and filesystem/container permissions on a filesystem supporting flock.\\nNever delete or replace .deploy.lock; its lock releases after every holder exits or the server restarts. Inspect execution and recovery state after forced termination.\\nPartial updates require a successful full installation with matching ports/layout. Steps return nonzero on failure; result-DEPLOYMENT_ID.json records the outcome.\\nThe bundle contains private runtime configuration; transfer it securely.\\nIncluded images:\\n{images}\",\n \"deploy_bundleMetadata\": \"Application version: {version}\\nBuild ID: {buildId}\\nCompose file: {compose}\\nDeployment ID: {deploymentId}\",\n \"deploy_targetHost\": \"Required: Linux server address or SSH alias. Replace SERVER_HOST before running either upload script.\",\n \"deploy_targetPort\": \"SSH port, integer 1-65535; default 22.\",\n \"deploy_targetUsername\": \"SSH login username; default deploy. Requires write access to directory and container runtime permissions.\",\n \"deploy_targetIdentityFile\": \"Optional private key path on the computer running the upload script. Prefer an absolute path; empty uses ssh-agent/default keys. HAI_DEPLOY_IDENTITY_FILE overrides it.\",\n \"deploy_targetKnownHostsFile\": \"Optional known_hosts path on the computer running the upload script. Prefer an absolute path; empty uses OpenSSH defaults. HAI_DEPLOY_KNOWN_HOSTS_FILE overrides it.\",\n \"deploy_targetStrictHostKeyChecking\": \"Boolean, default true: trust new host keys and reject changed keys. false disables host key checking.\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH connection timeout in seconds, integer 1-2147483647; default 10.\",\n \"deploy_targetDirectory\": \"Required absolute application directory on the Linux server; contains incoming packages, releases and successful current state. Parent-directory traversal is forbidden.\",\n \"deploy_targetBundle\": \"Required tar filename in the parent of this deployment directory. Keep the tar and this entire directory together when moving them.\",\n \"deploy_bundleOnlyContainer\": \"Compose bundle generation is supported only by docker-ssh.\",\n \"deploy_selectedContainerOnly\": \"Selected-service deployment requires a docker-ssh Compose destination.\",\n \"deploy_selectionInvalid\": \"Cannot deploy {service}: check the service name and build its image first.\",\n \"deploy_imageVersionRequired\": \"Specify an image version; latest is not allowed: {image}\",\n \"deploy_bundleRuntimeRequired\": \"Start local Podman/Docker to export middleware images, or prepare this complete offline bundle on the build machine.\",\n \"deploy_bundleFailed\": \"Package preparation or deployment failed: {reason}\",\n \"deploy_configFileInvalid\": \"Invalid YAML in {path}, line {line}. Check indentation, colons and quotes.\",\n \"deploy_configFileUnreadable\": \"Cannot read configuration file {path}. Check its path and permissions.\",\n \"deploy_bundleNameInvalid\": \"Bundle filenames may contain letters, numbers, dots, plus signs, hyphens and underscores; parent directories may contain spaces.\",\n \"deploy_localStopped\": \"The local command process tree has been confirmed exited.\",\n \"deploy_localUnknown\": \"Local process tree termination is unconfirmed; inspect local execution state.\",\n \"deploy_localNotStarted\": \"The local command was not started.\",\n \"deploy_commandOutputFailed\": \"Command output or callback failed\",\n \"deploy_commandInputFailed\": \"Command input failed\",\n \"deploy_commandTreeActive\": \"Child processes remain active after the main command exited\",\n \"deploy_commandExecutionFailed\": \"Command execution failed\",\n \"deploy_remoteUnknown\": \"Remote execution is unknown. Local SSH termination does not prove remote deployment stopped; inspect the server result and actual containers.\",\n \"deploy_remoteFinished\": \"A matching server result confirms the deployment script and recovery finished: stage {stage}, exit {code}. Verify actual service health.\",\n \"deploy_bundleDirectoryExists\": \"Delivery directory already exists: {path}. Choose another output name to preserve the existing bundle.\",\n \"deploy_bundleFull\": \"Full deployment\",\n \"deploy_bundlePartial\": \"Partial deployment (requires a successful full baseline)\",\n \"deploy_bundleSelection\": \"Deployment mode: {mode}\\nSelected services: {services}; see partial and selectedServices in manifest.json.\",\n \"deploy_transportBodyLimitInvalid\": \"Invalid transport.maxPlaintextBytes: use an integer from 1024 to 67108864 bytes\",\n \"deploy_transportKeyRingInvalid\": \"The transport key ring is missing or invalid; the application has not been uploaded. Set HAI_CRYPTO_TRANSPORT_SERVERKEYRING in {path} or the deployment process using complete valid JSON, and distribute the same managed ring to every node.\",\n \"deploy_uploadPasswordPrompt\": \"Enter SSH password (hidden)\",\n \"deploy_uploadPasswordUnavailable\": \"Interactive password input is unavailable. Set this operator environment variable before running the deployment script again.\",\n \"deploy_uploadPasswordCancelled\": \"Password input cancelled; no server connection was made.\",\n \"deploy_uploadPasswordInvalid\": \"SSH passwords must contain 1–1023 UTF-8 bytes without line breaks.\",\n \"deploy_managedSecretsInvalid\": \"Invalid generated middleware credential candidates. Rebuild the deployment bundle; server credentials will not be rotated automatically.\",\n \"deploy_secretImportFailed\": \"Legacy credential import was rejected during {phase}; check private input permissions, project/volume identity, live credentials and the deployment lock. No services were updated; inspect the protected state file if commit is unconfirmed\",\n \"deploy_projectNameRequired\": \"The root package.json.name is missing or cannot be normalized into an image and deployment resource identity.\",\n \"deploy_projectNameOverrideRemoved\": \"Deployment identity comes from the root package.json.name; remove the obsolete projectName override.\",\n \"deploy_requestAccessInvalid\": \"Invalid request access policy ({field}). Check fields, IP addresses, timezones and time windows. For a file reference, use readable YAML no larger than 1 MiB. Fix the configuration and create a new bundle.\",\n \"deploy_httpsPortsInvalid\": \"HTTP and HTTPS ports must differ; Let’s Encrypt HTTP-01 requires host port 80.\",\n \"deploy_httpsCertificateInvalid\": \"Invalid HTTPS certificate. Check readable PEM files, matching unencrypted private key, validity dates and domain, then repackage.\",\n \"deploy_bundleRuntime\": \"Runtime configuration and activation:\\nThis release record: {directory}/releases/{deploymentId}\\nNode backends read the file mounted at /run/hai/.env.runtime. Incremental deployments may retain an older record; current alone does not identify it. Inspect Source with docker inspect --format '{{json .Mounts}}' <container>.\\nFor ordinary backend settings: back up, edit that file, run docker restart <container> (or Podman), then verify health and affected business flows. HAI parents override children; managed connections in middleware.env take precedence.\\nStatic Web/middleware settings injected by Compose env_file require container recreation. Ports, mounts, Nginx routes/limits and HTTPS layout require a new full deployment bundle. Changing the website base also requires rebuilding artifacts.\\nCopy permanent edits back to the packaging source environment; the next release regenerates these files.\",\n \"deploy_bundleHttpOnly\": \"HTTPS: disabled. This bundle exposes HTTP port {port}, contains no certificate attachment and will not request a certificate on the server.\",\n \"deploy_bundleHttps\": \"HTTPS: enabled, https://{domain}:{port}; mode {mode}.\\nServer certificate: {certificates}/fullchain.pem; private key: {certificates}/privkey.pem. Mounted read-only at /etc/nginx/tls/.\\nEdit expose.https in HAI_DEPLOY_PROVIDER in the packaging environment .env.{environment}.local, or the unshadowed hai.json.deploy.provider.expose.https. Enable/disable, mode, domain or port changes require a new full bundle; editing .env.runtime and restarting does not issue a certificate for a new domain.\",\n \"deploy_bundleAcme\": \"Persistent Certbot state: {state}; current certificate entry: {state}/live/{domain}. Packaging does not contact the CA; issuance runs during server deployment, followed by automatic renewal. Public port 80 and root /.well-known/acme-challenge/ must remain reachable independently of the business context path.\",\n \"deploy_bundleAccounts\": \"Initial account variables (names and sources only; passwords omitted):\\n{sources}\\nApplications with matching bootstrap logic use HAI_CONFIG_ADMIN_PASSWORD to create the config_admin configuration administrator. HAI_ADMIN_DEFAULT_PASSWORD, HAI_AUDIT_ADMIN_PASSWORD and HAI_BUSINESS_OPERATOR_PASSWORD belong to the other template roles.\\nFullstack creation generates independent initial passwords per environment. Packaging reads the selected environment and process overrides; server deployment does not generate new application account passwords. Startup creates missing configured accounts; changing variables does not reset existing passwords or restore old roles. Custom applications without this bootstrap follow their own implementation.\",\n \"deploy_bundleDirectories\": \"Server directory guide (root {directory}):\\nincoming/: uploaded archive and .contents extraction; this upload is removed after success, retained after failure or unknown execution for diagnosis.\\nreleases/{deploymentId}/: runtime files and recovery records. images/ is not copied here; images live in the container engine and database/object data in volumes.\\ncompose.json defines services; compose-entry.json, proxy-entry.json and compose-files combine full/incremental releases and proxy overrides.\\n.env.runtime, middleware.env, middleware-runtime.env and runtime-env.mjs load application/middleware environments; web.conf is the proxy and request-access.yml the verified policy snapshot.\\nmanifest.json, image-list, services, dependencies, layout, web-base-path, storage-routing and health-paths record artifacts and probes. apply.sh and resolve-*.sh apply and validate state; SHA256SUMS verifies delivery content.\\nmanaged-* and state-backends describe bundle credential candidates and volume/backend bindings. Root managed-secrets.env holds long-lived server credentials; persistent-backends is the backend ledger. Back them up together with data volumes.\\ncurrent is a text file containing the last locally successful server release ID. Inspect result-{deploymentId}.json stage/exitCode/recoveryStatus and steps-{deploymentId}.jsonl; a release directory alone does not prove success.\\nActive containers and incremental composition may reference older releases. Check every active mount and compose-files before cleanup; retaining only current is insufficient.\"\n}\n","{\n \"deploy_notInitialized\": \"デプロイモジュールが初期化されていません。先にdeploy.init()を呼び出してください\",\n \"deploy_initFailed\": \"デプロイモジュールの初期化に失敗しました: {error}\",\n \"deploy_unsupportedProviderType\": \"未対応のデプロイプロバイダーの種類です: {type}\",\n \"deploy_unsupportedProvisionerType\": \"未対応のサービスプロビジョナーの種類です: {type}\",\n \"deploy_configTokenRequired\": \"デプロイプロバイダーのトークンは必須です\",\n \"deploy_authRequired\": \"認証が必要です\",\n \"deploy_authFailed\": \"認証に失敗しました: {error}\",\n \"deploy_projectCreateFailed\": \"プロジェクトの作成に失敗しました: {error}\",\n \"deploy_uploadFailed\": \"ビルド成果物のアップロードに失敗しました: {error}\",\n \"deploy_deployFailed\": \"デプロイに失敗しました: {error}\",\n \"deploy_provisionFailed\": \"サービスの準備に失敗しました: {service} - {error}\",\n \"deploy_adapterMissing\": \"対象プラットフォームのアダプターが見つかりません。{adapter}をインストールしてください\",\n \"deploy_scanFailed\": \"アプリケーションのスキャンに失敗しました: {error}\",\n \"deploy_envVarFailed\": \"環境変数の設定に失敗しました: {error}\",\n \"deploy_credentialError\": \"認証情報の読み書きに失敗しました: {error}\",\n \"deploy_credentialInvalidKey\": \"未対応の認証情報キーです: {key}。HAI_DEPLOY_*キーのみ使用できます\",\n \"deploy_credentialSaved\": \"認証情報を保存しました\",\n \"deploy_credentialLoaded\": \"認証情報を読み込みました\",\n \"deploy_configError\": \"デプロイ設定エラー: {error}\",\n \"deploy_credentialMissing\": \"認証情報の項目が不足しています: {fields}\",\n \"deploy_apiError\": \"{service} APIエラー({status})\",\n \"deploy_fileUploadFailed\": \"ファイルのアップロードに失敗しました({status})\",\n \"deploy_provisionNoResult\": \"{service}から接続情報が返されませんでした\",\n \"deploy_recoveryFailure\": \"{stage}でデプロイを停止しました。復旧情報を確認してください。\",\n \"deploy_recoverySuggestion\": \"同じプロジェクト名で再試行する前に、プロバイダーのコンソールで記載されたリソースを確認してください。「不明」は、リクエストによってリソースが作成された可能性を示します。再利用したリソースは自動削除されません。新規リソースは使用状況を確認してから手動で削除してください。\",\n \"deploy_commandTimeout\": \"コマンドがタイムアウトしました: {command}\",\n \"deploy_commandFailed\": \"コマンドに失敗しました({command}): {error}\",\n \"deploy_remoteConnectFailed\": \"リモートホスト{host}に接続できません: {error}\",\n \"deploy_remoteRuntimeMissing\": \"リモートホストにコンテナーランタイムまたはcomposeがありません: {runtime}\",\n \"deploy_imageTransferFailed\": \"イメージの転送に失敗しました: {error}\",\n \"deploy_healthCheckFailed\": \"ヘルスチェックに失敗しました。{url}でアプリの準備が完了していません\",\n \"deploy_invalidEnvironment\": \"環境名には英数字、アンダースコア、ハイフンを使用してください。local/exampleは予約されています。\",\n \"deploy_environmentMissing\": \"環境ファイルがありません: {path}。デプロイ前に作成して設定してください。\",\n \"deploy_environmentReadFailed\": \"デプロイ用の環境ファイルを読み取れません。構文と権限を確認してください。\",\n \"deploy_environmentWriteFailed\": \"デプロイ設定を保存できません。ファイルの構文と権限を確認してください。\",\n \"deploy_multipleApplications\": \"サービスパッケージが複数見つかりました。アプリケーションのディレクトリを指定してください。\",\n \"deploy_purposeSqlite\": \"ボリュームに永続化するローカルリレーショナルデータベース\",\n \"deploy_purposeDatabase\": \"業務データ用のリレーショナルデータベースサービス\",\n \"deploy_purposeMemory\": \"プロセス単位のメモリーキャッシュ。再起動時に消去され、外部サービスは使用しません\",\n \"deploy_purposeLocal\": \"ボリュームに永続化するローカルファイルストレージ\",\n \"deploy_purposeCache\": \"共有キャッシュ、セッション、分散ロック\",\n \"deploy_purposeStorage\": \"アップロードファイル用のS3互換オブジェクトストレージ\",\n \"deploy_purposeVector\": \"ベクトルのインデックス作成と類似検索\",\n \"deploy_purposeDisabled\": \"LDAPログインは無効です。ディレクトリサービスは作成しません\",\n \"deploy_purposeLdap\": \"ディレクトリアカウント認証。既定のディレクトリには業務ユーザーはいません\",\n \"deploy_purposeConsole\": \"配信せず、アプリケーションログにメッセージを出力します\",\n \"deploy_purposeEmail\": \"メール/HTTP配信。既定のSMTPコンテナーはテストメッセージのみ受信します\",\n \"deploy_purposeSms\": \"Aliyunの認証情報によるSMS。既存の署名と利用枠が必要です\",\n \"deploy_webProxyInvalid\": \"APIプレフィックスは、英数字、アンダースコア、ハイフン、スラッシュのみを含む絶対パスで指定してください。\",\n \"deploy_webBaseConflict\": \"サイトのマウントパスがAPIまたはヘルスチェックと競合しています。別のPUBLIC_BASE_PATHを指定してください。\",\n \"deploy_storageProxyInvalid\": \"ストレージプロキシを生成できません。有効な DNS バケット名を指定し、サイト、API、ヘルスチェックのパスとの重複を避けてください。\",\n \"deploy_storagePublicEndpointInvalid\": \"storage.publicEndpoint が無効です。ブラウザーから到達可能な HTTP(S) アドレスに有効なプロキシパスを指定できます。バケット、認証情報、クエリ、フラグメントは含めないでください。\",\n \"deploy_storageBackendRequired\": \"静的ブラウザアプリにはサーバー用ストレージ認証情報を配置できません。Serv または SvelteKit で Storage を設定し、API 経由で署名付きリンクを取得してください。\",\n \"deploy_artifactInvalid\": \"イメージ成果物が存在しないか、無効です。pnpm build --target image を実行するか、--artifact-dir で有効な成果物を選択するか、pnpm run deploy --build を使用してください。\",\n \"deploy_sshRequired\": \"自動デプロイにはSSH設定が必要です。サーバーに接続できない場合は--bundle-onlyで手動転送用のバンドルを生成してください。\",\n \"deploy_sshPasswordInvalid\": \"SSHパスワードは空にできず、CR/LF/NULを含められません。UTF-8で1023バイト以下にしてください。\",\n \"deploy_sshAskpassFailed\": \"管理対象のSSHパスワードhelperを準備できません。OpenSSHとWindows PowerShell 5を確認してください。\",\n \"deploy_sshAskpassCleanupFailed\": \"今回のSSHパスワードhelperの削除を確認できませんでした。ローカル一時ディレクトリを確認してください。\",\n \"deploy_targetAuth\": \"認証方式:keyは秘密鍵またはssh-agent、passwordはpasswordEnvが指定するローカル環境変数を使用します。\",\n \"deploy_targetPasswordEnv\": \"値ではなく環境変数名だけを保存します。操作端末の環境を優先し、不足時は今回だけ非表示で入力します。既定値は HAI_DEPLOY_PROVIDER_SSH_PASSWORD です。\",\n \"deploy_bundleInstructions\": \"バンドル:{file}\\n選択したサービスに必要なすべてのイメージを含みます(セルフホストのミドルウェアを含む)。\\nSSH を使用する場合、同じ交付ディレクトリの deploy-target.json を _comments に従って編集し、同じ場所で deploy.ps1(Windows)または deploy.sh(Linux/macOS)を実行してください。両方ともこの JSON を読み込みます。sh の実行にはローカルの awk も必要です。\\n隔離されたサーバーには交付ディレクトリ全体をコピーし、sh deploy-local.sh を実行します。自動展開と配置を実行し、ログを保持します。第1引数でサーバーの配置先を上書きできます。\\nLinux には Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux の flock が必要です。flock に対応したファイルシステム上で、ファイルシステムとコンテナーの操作権限も必要です。\\n.deploy.lock は削除も置換もしないでください。すべての保持プロセスが終了するか、サーバーが再起動するとロックが解放されます。強制終了後は実行状態と復旧状態を確認してください。\\n部分更新にはポートと構成が一致する正常な完全インストールが必要です。各手順は失敗時に非ゼロで終了し、result-DEPLOYMENT_ID.json に結果を記録します。\\nバンドルには非公開の実行時設定が含まれます。安全に転送してください。\\n同梱イメージ:\\n{images}\",\n \"deploy_bundleMetadata\": \"アプリのバージョン: {version}\\nビルドID: {buildId}\\nComposeファイル: {compose}\\nデプロイ ID: {deploymentId}\",\n \"deploy_targetHost\": \"必須:Linux サーバーのアドレスまたは SSH エイリアス。アップロードスクリプトを実行する前に SERVER_HOST を置き換えてください。\",\n \"deploy_targetPort\": \"SSH ポート。1〜65535の整数。既定値は22です。\",\n \"deploy_targetUsername\": \"SSH ログインユーザー名。既定値は deploy です。対象ディレクトリへの書き込み権限とコンテナーランタイムの操作権限が必要です。\",\n \"deploy_targetIdentityFile\": \"アップロードスクリプトを実行する端末上の秘密鍵パス(省略可)。絶対パスを推奨します。空欄では ssh-agent または既定の鍵を使用します。HAI_DEPLOY_IDENTITY_FILE で上書きできます。\",\n \"deploy_targetKnownHostsFile\": \"アップロードスクリプトを実行する端末上の known_hosts パス(省略可)。絶対パスを推奨します。空欄では OpenSSH の既定値を使用します。HAI_DEPLOY_KNOWN_HOSTS_FILE で上書きできます。\",\n \"deploy_targetStrictHostKeyChecking\": \"真偽値。既定値の true は新しいホスト鍵を信頼し、変更された鍵を拒否します。false はホスト鍵の検証を無効にします。\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH 接続タイムアウト(秒)。1〜2147483647の整数。既定値は10です。\",\n \"deploy_targetDirectory\": \"必須:Linux サーバー上のアプリケーションの絶対ディレクトリ。受信パッケージ、リリース、成功時の current 状態を保存します。親ディレクトリへの移動は許可されません。\",\n \"deploy_targetBundle\": \"必須:このデプロイディレクトリの親にある tar ファイル名。移動時は tar とこのディレクトリ全体を一緒に移動してください。\",\n \"deploy_bundleOnlyContainer\": \"Composeバンドルの生成はdocker-sshのみでサポートされます。\",\n \"deploy_selectedContainerOnly\": \"サービスを選択したデプロイには docker-ssh Compose のデプロイ先が必要です。\",\n \"deploy_selectionInvalid\": \"{service} をデプロイできません。サービス名を確認し、先にイメージをビルドしてください。\",\n \"deploy_imageVersionRequired\": \"イメージのバージョンを指定してください。latest は使用できません:{image}\",\n \"deploy_bundleRuntimeRequired\": \"ミドルウェアイメージをエクスポートするにはローカルの Podman/Docker を起動するか、ビルド端末で完全なオフラインバンドルを作成してください。\",\n \"deploy_bundleFailed\": \"パッケージの準備またはデプロイに失敗しました:{reason}\",\n \"deploy_configFileInvalid\": \"{path} の {line} 行目の YAML が無効です。インデント、コロン、引用符を確認してください。\",\n \"deploy_configFileUnreadable\": \"設定ファイル {path} を読み込めません。パスと権限を確認してください。\",\n \"deploy_bundleNameInvalid\": \"バンドルのファイル名には英数字、ドット、プラス、ハイフン、アンダースコアを使用できます。親ディレクトリには空白を使用できます。\",\n \"deploy_localStopped\": \"ローカルコマンドのプロセスツリーの終了を確認しました。\",\n \"deploy_localUnknown\": \"ローカルプロセスツリーの終了は未確認です。ローカルの実行状態を確認してください。\",\n \"deploy_localNotStarted\": \"ローカルコマンドは起動していません。\",\n \"deploy_commandOutputFailed\": \"コマンド出力またはコールバックに失敗しました\",\n \"deploy_commandInputFailed\": \"コマンド入力に失敗しました\",\n \"deploy_commandTreeActive\": \"メインコマンド終了後も子プロセスが動作しています\",\n \"deploy_commandExecutionFailed\": \"コマンドの実行に失敗しました\",\n \"deploy_remoteUnknown\": \"リモートの実行状態は不明です。ローカル SSH の終了はリモートデプロイの停止を意味しません。サーバーの結果と実際のコンテナーを確認してください。\",\n \"deploy_remoteFinished\": \"対応するサーバーの結果により、デプロイスクリプトと復旧処理の終了を確認しました:段階 {stage}、終了コード {code}。実際のサービスの稼働状態を確認してください。\",\n \"deploy_bundleDirectoryExists\": \"交付ディレクトリは既に存在します: {path}。既存のバンドルを保持するため別の出力名を選択してください。\",\n \"deploy_bundleFull\": \"完全デプロイ\",\n \"deploy_bundlePartial\": \"部分デプロイ(正常な完全配置の基準が必要)\",\n \"deploy_bundleSelection\": \"デプロイ方式: {mode}\\n更新サービス: {services}。manifest.json の partial と selectedServices で確認できます。\",\n \"deploy_transportBodyLimitInvalid\": \"transport.maxPlaintextBytes は 1024 から 67108864 バイトの整数で指定してください\",\n \"deploy_transportKeyRingInvalid\": \"転送鍵リングが不足または不正のため、アプリはまだアップロードしていません。{path} またはデプロイプロセスの HAI_CRYPTO_TRANSPORT_SERVERKEYRING に完全で有効な JSON を設定し、全ノードに同じ管理リングを配布してください。\",\n \"deploy_uploadPasswordPrompt\": \"SSH パスワードを入力(非表示)\",\n \"deploy_uploadPasswordUnavailable\": \"対話入力を利用できません。この操作端末の環境変数を設定してから配置スクリプトを再実行してください。\",\n \"deploy_uploadPasswordCancelled\": \"パスワード入力を中止しました。サーバーには未接続です。\",\n \"deploy_uploadPasswordInvalid\": \"SSH パスワードは改行を含まない 1–1023 UTF-8 バイトにしてください。\",\n \"deploy_managedSecretsInvalid\": \"自建ミドルウェアの候補認証情報が無効です。配置パッケージを再生成してください。サーバーの認証情報は自動変更されません。\",\n \"deploy_secretImportFailed\": \"旧認証情報のインポートは {phase} 段階で拒否されました。入力権限、プロジェクトとボリューム、実際の認証情報、デプロイロックを確認してください。サービスは更新されていません。確定が不明な場合は保護された状態ファイルを確認してください\",\n \"deploy_projectNameRequired\": \"工程ルートの package.json.name がないか正規化できないため、イメージとデプロイリソースの識別名を生成できません。\",\n \"deploy_projectNameOverrideRemoved\": \"デプロイ識別名は工程ルートの package.json.name から取得します。旧 projectName 上書き引数を削除してください。\",\n \"deploy_requestAccessInvalid\": \"リクエストアクセス設定({field})が無効です。フィールド、IP、タイムゾーン、時間帯を確認してください。ファイルは読み取り可能な 1 MiB 以下の YAML を指定し、修正後に再パッケージしてください。\",\n \"deploy_httpsPortsInvalid\": \"HTTP と HTTPS のポートは異なる必要があります。Let’s Encrypt HTTP-01 にはホストのポート 80 が必要です。\",\n \"deploy_httpsCertificateInvalid\": \"HTTPS 証明書が無効です。PEM ファイル、暗号化されていない秘密鍵との一致、有効期間、ドメインを確認し、再作成してください。\",\n \"deploy_bundleRuntime\": \"実行設定の変更と反映:\\n今回の配備記録:{directory}/releases/{deploymentId}\\nNode バックエンドは /run/hai/.env.runtime に実際にマウントされたファイルを読みます。差分配備では古い記録を参照するため current だけでは判定できません。docker inspect --format '{{json .Mounts}}' <コンテナ名> の Source を確認してください。\\n通常のバックエンド設定はバックアップ後に編集し、docker restart <コンテナ名>(Podman も同様)で反映してヘルスと業務を確認します。HAI 親設定と middleware.env の管理接続が優先します。\\nCompose env_file の静的 Web・ミドルウェア設定はコンテナ再作成、ポート・マウント・Nginx 経路/上限・HTTPS 構成は新しい全量配備が必要です。サイト base の変更は制品も再構築します。\\n恒久的な変更は元の環境へ戻してください。次回配備でファイルが再生成されます。\",\n \"deploy_bundleHttpOnly\": \"HTTPS:無効。HTTP ポート {port} のみを公開し、証明書は同梱せず、サーバーでも申請しません。\",\n \"deploy_bundleHttps\": \"HTTPS:有効、https://{domain}:{port}、モード {mode}。\\nサーバー証明書:{certificates}/fullchain.pem、秘密鍵:{certificates}/privkey.pem。コンテナの /etc/nginx/tls/ に読み取り専用でマウントします。\\n配布元 .env.{environment}.local の HAI_DEPLOY_PROVIDER 内 expose.https、または上書きされていない hai.json.deploy.provider.expose.https を編集します。有効/無効、モード、ドメイン、ポート変更は新しい全量配備が必要です。.env.runtime の編集と再起動では新ドメインの証明書を申請しません。\",\n \"deploy_bundleAcme\": \"Certbot 永続状態:{state}、現在の証明書入口:{state}/live/{domain}。パッケージ時は CA に接続せず、サーバー配備時に申請し、その後自動更新します。公開ポート 80 とルート /.well-known/acme-challenge/ は業務 context path と別に到達可能にしてください。\",\n \"deploy_bundleAccounts\": \"初期アカウント変数(名前と取得元のみ、パスワード非表示):\\n{sources}\\n対応する初期化を持つアプリでは HAI_CONFIG_ADMIN_PASSWORD が config_admin 設定管理者を作成します。HAI_ADMIN_DEFAULT_PASSWORD、HAI_AUDIT_ADMIN_PASSWORD、HAI_BUSINESS_OPERATOR_PASSWORD は他のテンプレート役割に対応します。\\nFullstack 作成時に環境ごとの独立初期パスワードを生成し、配布時は選択環境とプロセス上書きを読みます。サーバー配備で新たに生成しません。設定がある未作成アカウントを起動時に作り、既存のパスワードや変更後の役割は変数変更で戻しません。独自アプリは実装に従います。\",\n \"deploy_bundleDirectories\": \"サーバーディレクトリ(ルート {directory}):\\nincoming/:アップロードと .contents 展開先。成功時に今回分を削除し、失敗・実行不明時は調査用に保持します。\\nreleases/{deploymentId}/:実行ファイルと復旧記録。images/ はコピーせずイメージはコンテナエンジン、DB・オブジェクトデータはボリュームに保存します。\\ncompose.json はサービス定義、compose-entry.json・proxy-entry.json・compose-files は全量/差分とプロキシ上書きの組合せです。\\n.env.runtime・middleware.env・middleware-runtime.env・runtime-env.mjs は環境、web.conf はプロキシ、request-access.yml は検証済みポリシーです。\\nmanifest.json・image-list・services・dependencies・layout・web-base-path・storage-routing・health-paths は制品/依存/プローブ、apply.sh・resolve-*.sh は配備と状態検証、SHA256SUMS は配布整合性用です。\\nmanaged-*・state-backends は候補資格情報とボリューム/バックエンドの対応です。ルート managed-secrets.env は永続資格情報、persistent-backends は台帳で、データボリュームと一緒にバックアップします。\\ncurrent は最後にサーバー内で成功した ID のテキストファイルです。result-{deploymentId}.json の stage/exitCode/recoveryStatus と steps-{deploymentId}.jsonl を確認し、release の存在だけで成功と判断しません。\\n差分構成と実行コンテナは古い release を参照できます。整理前に全 Mounts と compose-files を確認し、current 以外を一律削除しないでください。\"\n}\n","{\n \"deploy_notInitialized\": \"Deploy 模块尚未初始化,请先调用 deploy.init()\",\n \"deploy_initFailed\": \"Deploy 模块初始化失败:{error}\",\n \"deploy_unsupportedProviderType\": \"不支持的部署平台类型:{type}\",\n \"deploy_unsupportedProvisionerType\": \"不支持的服务 Provisioner 类型:{type}\",\n \"deploy_configTokenRequired\": \"部署平台 Token 不能为空\",\n \"deploy_authRequired\": \"请先完成认证\",\n \"deploy_authFailed\": \"认证失败:{error}\",\n \"deploy_projectCreateFailed\": \"项目创建失败:{error}\",\n \"deploy_uploadFailed\": \"构建产物上传失败:{error}\",\n \"deploy_deployFailed\": \"部署失败:{error}\",\n \"deploy_provisionFailed\": \"基础设施开通失败:{service} - {error}\",\n \"deploy_adapterMissing\": \"未检测到目标平台 adapter,请安装 {adapter}\",\n \"deploy_scanFailed\": \"应用扫描失败:{error}\",\n \"deploy_envVarFailed\": \"环境变量设置失败:{error}\",\n \"deploy_credentialError\": \"凭证读写失败:{error}\",\n \"deploy_credentialInvalidKey\": \"不支持的凭证键名:{key}。仅允许 HAI_DEPLOY_*\",\n \"deploy_credentialSaved\": \"凭证已保存\",\n \"deploy_credentialLoaded\": \"凭证已加载\",\n \"deploy_configError\": \"部署配置错误:{error}\",\n \"deploy_credentialMissing\": \"缺少凭证字段:{fields}\",\n \"deploy_apiError\": \"{service} API 请求失败({status})\",\n \"deploy_fileUploadFailed\": \"文件上传失败({status})\",\n \"deploy_provisionNoResult\": \"{service} 未返回连接信息\",\n \"deploy_recoveryFailure\": \"部署在 {stage} 阶段停止,请查看恢复清单。\",\n \"deploy_recoverySuggestion\": \"重试前在服务商控制台核对清单,并使用相同项目名。unknown 表示请求可能已创建资源。复用资源不会自动删除;新建资源仅在确认未被使用后人工清理。\",\n \"deploy_commandTimeout\": \"命令执行超时:{command}\",\n \"deploy_commandFailed\": \"命令执行失败({command}):{error}\",\n \"deploy_remoteConnectFailed\": \"无法连接远程主机 {host}:{error}\",\n \"deploy_remoteRuntimeMissing\": \"远程主机缺少容器运行时或 compose:{runtime}\",\n \"deploy_imageTransferFailed\": \"镜像传输失败:{error}\",\n \"deploy_healthCheckFailed\": \"健康检查失败,应用未在 {url} 就绪\",\n \"deploy_invalidEnvironment\": \"环境名称仅允许字母、数字、下划线和连字符,且不能使用 local/example。\",\n \"deploy_environmentMissing\": \"缺少环境配置 {path};请先创建该文件并完成配置,再重新部署。\",\n \"deploy_environmentReadFailed\": \"部署环境文件读取失败,请检查文件格式与权限。\",\n \"deploy_environmentWriteFailed\": \"部署配置写入失败,请检查文件格式与权限。\",\n \"deploy_multipleApplications\": \"发现多个服务包,请指定要部署的应用目录。\",\n \"deploy_purposeSqlite\": \"本地文件关系数据库,使用持久化卷\",\n \"deploy_purposeDatabase\": \"独立关系数据库服务,保存业务数据\",\n \"deploy_purposeMemory\": \"单进程内存缓存,重启后清空,不创建外部服务\",\n \"deploy_purposeLocal\": \"本地文件存储,使用持久化卷\",\n \"deploy_purposeCache\": \"共享缓存、会话与分布式锁\",\n \"deploy_purposeStorage\": \"S3 兼容对象存储,保存上传文件\",\n \"deploy_purposeVector\": \"向量索引与相似度搜索\",\n \"deploy_purposeDisabled\": \"LDAP 登录未启用,不创建目录服务\",\n \"deploy_purposeLdap\": \"企业目录账号认证;默认目录不包含业务用户\",\n \"deploy_purposeConsole\": \"消息输出到应用日志,不实际投递\",\n \"deploy_purposeEmail\": \"邮件或 HTTP 通知投递;默认 SMTP 容器仅用于测试接收\",\n \"deploy_purposeSms\": \"通过阿里云凭证接入短信服务,需已有签名与额度\",\n \"deploy_webProxyInvalid\": \"API 前缀必须是仅含字母、数字、下划线、连字符和斜杠的绝对路径。\",\n \"deploy_webBaseConflict\": \"网站挂载目录与 API 或健康检查入口冲突,请使用不同的 PUBLIC_BASE_PATH。\",\n \"deploy_storageProxyInvalid\": \"无法生成对象存储代理:请使用有效的 DNS 桶名,并确保桶路径不与网站目录、API 或健康检查入口重叠。\",\n \"deploy_storagePublicEndpointInvalid\": \"storage.publicEndpoint 无效:请填写浏览器可访问的 HTTP(S) 地址,可包含规范的代理目录,不能包含桶名、凭据、查询或片段。\",\n \"deploy_storageBackendRequired\": \"静态浏览器应用不能部署存储服务端配置。请在 Serv 或 SvelteKit 服务中配置 Storage,再通过 API 获取预签名链接。\",\n \"deploy_artifactInvalid\": \"镜像产物缺失或校验失败。请先执行 pnpm build --target image,或用 --artifact-dir 指定有效产物;也可用 pnpm run deploy --build 一次完成。\",\n \"deploy_sshRequired\": \"自动部署需要 SSH 配置;无网络连接时使用 --bundle-only 生成部署包并手工搬运。\",\n \"deploy_sshPasswordInvalid\": \"SSH 密码不能为空或包含 CR/LF/NUL,UTF-8 长度不能超过 1023 字节。\",\n \"deploy_sshAskpassFailed\": \"无法准备受控 SSH 密码 helper;请检查系统 OpenSSH 和 Windows PowerShell 5。\",\n \"deploy_sshAskpassCleanupFailed\": \"无法确认本次 SSH 密码 helper 已清理,请检查本机临时目录。\",\n \"deploy_targetAuth\": \"认证方式:key 使用私钥或 ssh-agent;password 从 passwordEnv 指定的本机环境读取密码。\",\n \"deploy_targetPasswordEnv\": \"仅保存环境变量名,不是密码值。优先复用操作机环境变量;缺失时部署入口隐藏输入,仅本次使用。默认 HAI_DEPLOY_PROVIDER_SSH_PASSWORD。\",\n \"deploy_bundleInstructions\": \"部署包:{file}\\n包中已包含本次选择服务需要的镜像,包括自建中间件。\\n有 SSH 连接时,先按 _comments 说明修改同一交付目录中的 deploy-target.json,再运行同目录的 deploy.ps1(Windows)或 deploy.sh(Linux/macOS);两者均读取此 JSON,sh 入口还需本机安装 awk。\\n完全隔离时,把整个交付目录复制到 Linux 服务器,在该目录执行 sh deploy-local.sh;脚本自动解包、部署并保留日志。可传入第一个参数覆盖服务器部署目录。\\n服务器需要 Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux flock,以及支持 flock 的文件系统和目录、容器运行权限。\\n固定锁文件 .deploy.lock 禁止删除或替换;全部持有进程退出或重启后自动释放。强杀后的执行与恢复状态须人工核对。\\n部分更新要求服务器已有成功的完整部署,端口及应用布局保持一致。每步失败会返回非零退出码;结果记录在部署目录 result-部署ID.json。\\n包包含私有运行配置,请安全传输。\\n所含镜像:\\n{images}\",\n \"deploy_bundleMetadata\": \"应用版本:{version}\\n构建编号:{buildId}\\nCompose 文件:{compose}\\n部署 ID: {deploymentId}\",\n \"deploy_targetHost\": \"必填:Linux 服务器地址或 SSH 别名。执行任一上传脚本前,将 SERVER_HOST 改为实际地址。\",\n \"deploy_targetPort\": \"SSH 端口,1-65535 的整数,默认 22。\",\n \"deploy_targetUsername\": \"SSH 登录用户名,默认 deploy;需要目标目录写入权限及容器运行权限。\",\n \"deploy_targetIdentityFile\": \"可选:运行上传脚本的电脑上的私钥路径,建议绝对路径;留空使用 ssh-agent 或默认密钥。HAI_DEPLOY_IDENTITY_FILE 可覆盖。\",\n \"deploy_targetKnownHostsFile\": \"可选:运行上传脚本的电脑上的 known_hosts 路径,建议绝对路径;留空使用 OpenSSH 默认文件。HAI_DEPLOY_KNOWN_HOSTS_FILE 可覆盖。\",\n \"deploy_targetStrictHostKeyChecking\": \"布尔值,默认 true:首次信任新主机密钥,拒绝已变更密钥;false 关闭主机密钥检查。\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH 连接超时秒数,1-2147483647 的整数,默认 10。\",\n \"deploy_targetDirectory\": \"必填:Linux 服务器上的应用绝对目录,保存 incoming 部署包、releases 及成功状态 current;禁止 .. 父目录跳转。\",\n \"deploy_targetBundle\": \"必填:本部署操作目录上一级的 tar 文件名;搬运时请将 tar 和本目录完整放在一起。\",\n \"deploy_bundleOnlyContainer\": \"仅生成 Compose tar 只支持 docker-ssh。\",\n \"deploy_selectedContainerOnly\": \"按服务局部部署仅适用于 docker-ssh Compose 目标。\",\n \"deploy_selectionInvalid\": \"无法部署服务 {service}:请检查服务名称,并先构建对应镜像。\",\n \"deploy_imageVersionRequired\": \"镜像必须指定版本,不能使用 latest:{image}\",\n \"deploy_bundleRuntimeRequired\": \"完整离线包需要导出中间件镜像。请启动本地 Podman/Docker,或在构建机打包。\",\n \"deploy_bundleFailed\": \"交付准备或部署失败:{reason}\",\n \"deploy_configFileInvalid\": \"配置文件 {path} 第 {line} 行格式有误。请检查缩进、冒号和引号后重试。\",\n \"deploy_configFileUnreadable\": \"无法读取配置文件 {path},请检查文件路径与读取权限。\",\n \"deploy_bundleNameInvalid\": \"部署包文件名只支持字母、数字、点、加号、短横线和下划线;所在目录可以包含空格。\",\n \"deploy_localStopped\": \"已确认本地命令进程树全部退出。\",\n \"deploy_localUnknown\": \"无法确认本地命令进程树已全部退出;请检查本机执行状态。\",\n \"deploy_localNotStarted\": \"本地命令尚未启动。\",\n \"deploy_commandOutputFailed\": \"命令输出或回调失败\",\n \"deploy_commandInputFailed\": \"命令输入失败\",\n \"deploy_commandTreeActive\": \"主命令退出后仍有活跃的子进程\",\n \"deploy_commandExecutionFailed\": \"命令执行失败\",\n \"deploy_remoteUnknown\": \"远端执行状态未知;本地 SSH 结束不证明远端部署已停止,请核对服务器结果与实际容器状态。\",\n \"deploy_remoteFinished\": \"匹配的服务器结果确认部署脚本及恢复已结束:阶段 {stage},退出码 {code}。请核对实际服务健康状态。\",\n \"deploy_bundleDirectoryExists\": \"交付目录已存在:{path}。请换一个输出名称,保留已有部署包。\",\n \"deploy_bundleFull\": \"全量部署\",\n \"deploy_bundlePartial\": \"增量部署(要求已有成功的全量基线)\",\n \"deploy_bundleSelection\": \"部署模式:{mode}\\n更新服务:{services};可在 manifest.json 中核对 partial 和 selectedServices。\",\n \"deploy_transportBodyLimitInvalid\": \"transport.maxPlaintextBytes 无效:必须是 1024 到 67108864 字节之间的整数\",\n \"deploy_transportKeyRingInvalid\": \"传输密钥环缺失或无效,尚未上传应用。请在 {path} 或部署进程中设置 HAI_CRYPTO_TRANSPORT_SERVERKEYRING,使用完整有效的 JSON,并向所有节点分发同一受管密钥环。\",\n \"deploy_uploadPasswordPrompt\": \"请输入 SSH 密码(隐藏输入)\",\n \"deploy_uploadPasswordUnavailable\": \"当前无法交互输入密码;请先设置该操作机环境变量,再重新运行部署脚本。\",\n \"deploy_uploadPasswordCancelled\": \"已取消密码输入,尚未连接服务器。\",\n \"deploy_uploadPasswordInvalid\": \"SSH 密码须为 1–1023 个 UTF-8 字节,且不能包含换行。\",\n \"deploy_managedSecretsInvalid\": \"自建中间件候选凭据无效,请重新生成部署包;服务器凭据不会自动更换。\",\n \"deploy_secretImportFailed\": \"旧凭据导入在 {phase} 阶段被拒绝;请核对私有输入权限、项目/卷身份、实际服务凭据及部署锁,未执行服务更新;提交结果不明时请核对受保护的状态文件\",\n \"deploy_projectNameRequired\": \"工程根 package.json.name 缺失或无法归一化,不能生成镜像与部署资源身份。\",\n \"deploy_projectNameOverrideRemoved\": \"部署项目名统一来自工程根 package.json.name;请移除旧 projectName 覆盖参数。\",\n \"deploy_requestAccessInvalid\": \"请求访问策略配置无效({field})。请检查字段、IP、时区及时间窗口;如引用文件,请确认文件可读、格式为 YAML 且不超过 1 MiB。修正后重新打包。\",\n \"deploy_httpsPortsInvalid\": \"HTTP 与 HTTPS 端口必须不同;Let’s Encrypt 的 HTTP-01 入口必须使用宿主机 80 端口。\",\n \"deploy_httpsCertificateInvalid\": \"HTTPS 证书无效:请核对 PEM 文件可读、证书与未加密私钥匹配、证书有效期及域名,然后重新打包。\",\n \"deploy_bundleRuntime\": \"运行配置与生效:\\n本次发布记录:{directory}/releases/{deploymentId}\\nNode 后端读取实际挂载到 /run/hai/.env.runtime 的文件;增量部署可能继续引用旧记录,不能只按 current 推断。用 docker inspect --format '{{json .Mounts}}' <容器名> 查看 Source。\\n普通后端配置:备份、修改该文件,然后 docker restart <容器名>(Podman 同理),核验健康与相关业务。HAI 父对象优先于叶子,middleware.env 的托管连接优先。\\nCompose env_file 注入的静态 Web/中间件环境变更需要重建容器;端口、挂载、Nginx 路由/限额、HTTPS 布局需要重新生成全量部署包。网站 base 变化还需要重新构建制品。\\n手工修改同步回打包源环境;下次发布会重新生成。\",\n \"deploy_bundleHttpOnly\": \"HTTPS:未启用。本包仅发布 HTTP 端口 {port},没有证书附件,也不会在服务器申请证书。\",\n \"deploy_bundleHttps\": \"HTTPS:已启用,https://{domain}:{port};模式 {mode}。\\n服务器证书:{certificates}/fullchain.pem;私钥:{certificates}/privkey.pem。容器只读挂载到 /etc/nginx/tls/。\\n修改本地打包环境 .env.{environment}.local 的 HAI_DEPLOY_PROVIDER 中 expose.https,或未被覆盖的 hai.json.deploy.provider.expose.https。启停、切换模式/域名/端口后生成新的全量部署包;修改 .env.runtime 并重启不能触发新域名签发。\",\n \"deploy_bundleAcme\": \"Certbot 持久状态:{state};当前证书入口:{state}/live/{domain}。打包不请求 CA,服务器部署时申请,之后自动续期。公网 80 端口及根路径 /.well-known/acme-challenge/ 必须可达,不能只允许业务 context path。\",\n \"deploy_bundleAccounts\": \"初始账号变量(只列名称和来源,不显示密码):\\n{sources}\\nHAI_CONFIG_ADMIN_PASSWORD 供有相应引导逻辑的应用创建 config_admin 配置管理员;HAI_ADMIN_DEFAULT_PASSWORD、HAI_AUDIT_ADMIN_PASSWORD、HAI_BUSINESS_OPERATOR_PASSWORD 对应其他模板职责账号。\\nCLI 创建 Fullstack 时为各环境生成独立初始密码;打包读取所选环境与进程覆盖,不会因服务器部署再生成应用账号密码。有配置且账号缺失时由应用启动引导;已有账号不会因修改变量重置密码或恢复旧职责。无相应引导逻辑的自定义应用以自身实现为准。\",\n \"deploy_bundleDirectories\": \"服务器目录说明(根目录 {directory}):\\nincoming/:上传归档和 .contents 解包目录;成功后清理本次内容,失败或执行未知时保留排障证据。\\nreleases/{deploymentId}/:本次运行文件和恢复记录;不复制 images/,镜像导入容器引擎,数据库和对象数据保存在数据卷。\\ncompose.json 是服务定义;compose-entry.json、proxy-entry.json、compose-files 组合全量/增量及代理覆盖。\\n.env.runtime、middleware.env、middleware-runtime.env、runtime-env.mjs 负责应用与中间件环境;web.conf 是代理,request-access.yml 是校验后的策略快照。\\nmanifest.json、image-list、services、dependencies、layout、web-base-path、storage-routing、health-paths 是制品、依赖和探活元数据;apply.sh、resolve-*.sh 执行发布及状态核验;SHA256SUMS 校验交付内容。\\nmanaged-*、state-backends 描述本包的凭据候选和卷/后端绑定。根目录 managed-secrets.env 是服务器长期凭据,persistent-backends 是长期后端账本,须与数据卷成套备份。\\ncurrent 是最后服务器本地成功发布 ID 的普通文本文件;查看 result-{deploymentId}.json 的 stage/exitCode/recoveryStatus 和 steps-{deploymentId}.jsonl 判断本次结果。仅出现 release 目录不代表成功。\\n增量部署和运行容器可能引用旧 release;清理前核对所有活动挂载和 compose-files,不能只保留 current。\"\n}\n","/**\n * @h-ai/deploy — i18n\n *\n * 本文件提供部署模块的 i18n 文案访问入口。\n * @module deploy-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesJaJP from '../messages/ja-JP.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\n// ─── i18n ───\n\n/**\n * 部署模块文案 Key 类型\n * 从现有中文字典推导消息键,避免内部实现使用未注册的翻译。\n * @example 模块内部上下文\n * ```ts\n * const key: DeployMessageKey = 'deploy_notInitialized'\n * const message = deployM(key)\n * ```\n */\ntype DeployMessageKey = keyof typeof messagesZhCN\n\n/**\n * 获取部署模块文案\n * 使用 core 请求/全局 locale 的现有中英字典;不自行缓存调用时的语言。\n * @param key - 文案 Key\n * @param options - 插值参数与格式化选项\n * @returns 本地化后的文案字符串\n * @example 模块内部上下文\n * ```ts\n * const message = deployM('deploy_sshRequired')\n * ```\n */\nexport const deployM = core.i18n.createMessageGetter<DeployMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n 'ja-JP': messagesJaJP,\n})\n","/**\n * @h-ai/deploy — 部署配置 Schema\n *\n * 本文件定义部署模块的 Zod Schema 和配置类型;错误定义位于 deploy-types.ts。\n * @module deploy-config\n */\n\nimport { z } from 'zod'\nimport { deployM } from './deploy-i18n.js'\n\n// ─── Provider 配置 Schema ───\n\n/** Vercel 部署平台配置 */\nconst VercelProviderConfigSchema = z.object({\n type: z.literal('vercel'),\n token: z.string().min(1, deployM('deploy_configTokenRequired')),\n})\n\n/** SSH 连接配置(docker-ssh Provider 使用 OpenSSH 客户端连接远程主机) */\nconst SshConfigSchema = z.object({\n /** 远程主机地址或 ~/.ssh/config 中的 Host 别名 */\n host: z.string().regex(/^[a-z0-9][a-z0-9.:-]*$/i),\n /** SSH 端口 */\n port: z.number().int().min(1).max(65535).default(22),\n /** SSH 用户名 */\n username: z.string().regex(/^[a-z_][\\w-]*$/i),\n /** 认证方式;省略时非空 password 使用密码,否则保留私钥/agent;显式 key 忽略残留密码。 */\n auth: z.enum(['key', 'password']).optional(),\n /** SSH 密码(保留原值);密码方式必须非空、无 CR/LF/NUL,UTF-8 不超过 1023 字节。 */\n password: z.string().optional(),\n /** 私钥文件路径(省略时使用 ssh-agent 或 ~/.ssh 默认密钥) */\n identityFile: z.string().min(1).optional(),\n /** known_hosts 文件路径(省略时使用默认;配合 CI/临时环境隔离主机指纹) */\n knownHostsFile: z.string().min(1).optional(),\n /** 严格主机密钥校验,默认开启(true→accept-new 首次信任并拒绝变更;false→关闭校验) */\n strictHostKeyChecking: z.boolean().default(true),\n /** 连接超时(秒) */\n connectTimeoutSeconds: z.number().int().positive().default(10),\n}).superRefine((ssh, context) => {\n // 未启用的旧密码不影响显式 key;空串不改变省略 auth 时的原有默认行为。\n if (ssh.auth === 'key' || (ssh.auth === undefined && !ssh.password))\n return\n if (!ssh.password || /[\\r\\n\\0]/.test(ssh.password) || new TextEncoder().encode(ssh.password).length > 1023)\n context.addIssue({ code: 'custom', path: ['password'], message: deployM('deploy_sshPasswordInvalid') })\n})\n\n/** 入口域名同时用于证书校验、Nginx 与公开 URL,禁止配置指令或路径。 */\nconst HttpsDomainSchema = z.string().max(253).regex(/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i).refine(value => !value.includes('..'))\nconst httpsOptions = {\n /** 公开访问域名;同时用于证书身份校验和 Nginx 入口。 */\n domain: HttpsDomainSchema.describe('HTTPS 公开域名;证书必须匹配该域名'),\n /** HTTPS 宿主端口,与 HTTP 端口不同。 */\n port: z.number().int().min(1).max(65535).default(443).describe('HTTPS 宿主端口,默认 443,须与 HTTP 端口不同'),\n /** 是否将普通 HTTP 请求跳转到 HTTPS。 */\n redirectHttp: z.boolean().default(true).describe('普通 HTTP 请求是否以 308 跳转至 HTTPS,健康检查和 ACME 挑战除外'),\n}\nconst HttpsConfigSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('files'),\n ...httpsOptions,\n /** 相对于工程根或绝对路径的 PEM 完整证书链及未加密私钥。 */\n certificateFile: z.string().min(1).describe('PEM 完整证书链路径,相对工程根或绝对路径;打包时复制到私有发布目录'),\n privateKeyFile: z.string().min(1).describe('未加密 PEM 私钥路径,相对工程根或绝对路径;必须与证书匹配'),\n }),\n z.object({\n type: z.literal('letsencrypt'),\n ...httpsOptions,\n domain: HttpsDomainSchema.refine(value => value.includes('.') && !/^\\d+(?:\\.\\d+){3}$/.test(value)).describe('Let’s Encrypt 单个公网域名,使用 HTTP-01,不支持 IP 或通配符'),\n email: z.email().describe('Let’s Encrypt 账号联系邮箱'),\n /** 使用者须明确同意 Let's Encrypt 的服务条款。 */\n acceptTerms: z.literal(true).describe('明确同意 Let’s Encrypt 服务条款后才可设置为 true'),\n }),\n])\n\n/** HTTP 端口及可选 HTTPS 入口;Let's Encrypt 使用 HTTP-01,HTTP 必须映射 80。 */\nconst PortExposeSchema = z.object({\n type: z.literal('port').default('port'),\n /** 容器内监听端口(adapter-node 默认 3000) */\n containerPort: z.number().int().min(1).max(65535).default(3000),\n /** 宿主机映射端口 */\n hostPort: z.number().int().min(1).max(65535),\n /** 可选 HTTPS:已有 PEM 文件或官方 Certbot 自动申请续期;省略保留 HTTP。 */\n https: HttpsConfigSchema.optional().describe('可选 HTTPS 入口;files 使用已有证书,letsencrypt 使用官方 Certbot 申请续期,省略保持 HTTP'),\n}).superRefine((expose, context) => {\n if (expose.https && (expose.https.port === expose.hostPort || (expose.https.type === 'letsencrypt' && expose.hostPort !== 80)))\n context.addIssue({ code: 'custom', path: ['https'], message: deployM('deploy_httpsPortsInvalid') })\n})\n\n/** 应用入口:HTTP 及统一的可选 HTTPS。 */\nconst ExposeSchema = PortExposeSchema\n\n/** docker-ssh 部署平台配置 */\nconst DockerSshProviderConfigSchema = z.object({\n type: z.literal('docker-ssh'),\n /** SSH 连接参数 */\n ssh: SshConfigSchema.optional(),\n /** 远程主机运行参数 */\n remote: z.object({\n /** 远程应用根目录 */\n baseDir: z.string().regex(/^\\/[\\w/. -]+$/).refine(value => !value.split('/').includes('..')).default('/opt/hai/apps'),\n /** 远程容器运行时(auto 优先 podman) */\n runtime: z.enum(['auto', 'docker', 'podman']).default('auto'),\n }).default({ baseDir: '/opt/hai/apps', runtime: 'auto' }),\n /** 应用暴露方式 */\n expose: ExposeSchema,\n /** Nginx 前方可信负载均衡的 IP/CIDR;省略时不接受外部转发头。 */\n trustedEdgeProxies: z.array(z.union([z.ipv4(), z.ipv6(), z.cidrv4(), z.cidrv6()])).max(1000).optional(),\n})\n\n/**\n * 部署平台配置联合类型(后续可扩展更多平台)\n * 按 type 区分 Vercel 与 docker-ssh;仅校验配置形状,不验证远端连通性或云凭据。\n * @example\n * ```ts\n * import { ProviderConfigSchema } from '@h-ai/deploy'\n * const result = ProviderConfigSchema.safeParse({ type: 'docker-ssh', expose: { hostPort: 8080 } })\n * if (!result.success) throw new Error('Invalid deployment provider')\n * const provider = result.data\n * ```\n */\nexport const ProviderConfigSchema = z.discriminatedUnion('type', [\n VercelProviderConfigSchema,\n DockerSshProviderConfigSchema,\n])\n\n/**\n * SSH 连接配置(parse 后)\n * 这是 Schema 解析后的类型,默认字段已必填;auth 省略时非空密码选择 password,否则使用 ssh-agent/默认密钥;显式 key 忽略残留 password。\n * @example\n * ```ts\n * import type { SshConfig } from '@h-ai/deploy'\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * ```\n */\nexport type SshConfig = z.infer<typeof SshConfigSchema>\n\n/**\n * 端口暴露配置(parse 后)\n * @example\n * ```ts\n * import type { PortExposeConfig } from '@h-ai/deploy'\n * const ports: PortExposeConfig = { type: 'port', hostPort: 8080, containerPort: 3000 }\n * ```\n */\nexport type PortExposeConfig = z.infer<typeof PortExposeSchema>\n\n/**\n * docker-ssh 部署平台配置(parse 后)\n * SSH 可省略用于离线打包;真正在线发布必须提供 SSH 配置。\n * @example\n * ```ts\n * import type { DockerSshProviderConfig } from '@h-ai/deploy'\n * const provider: DockerSshProviderConfig = { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } }\n * ```\n */\nexport type DockerSshProviderConfig = z.infer<typeof DockerSshProviderConfigSchema>\n\n// ─── Provisioner 配置 Schema ───\n\n/** Neon PostgreSQL 服务配置 */\nconst NeonServiceSchema = z.object({\n provisioner: z.literal('neon'),\n apiKey: z.string().min(1),\n})\n\n/** Upstash Redis 服务配置 */\nconst UpstashServiceSchema = z.object({\n provisioner: z.literal('upstash'),\n email: z.string().email(),\n apiKey: z.string().min(1),\n})\n\n/** Cloudflare R2 存储服务配置 */\nconst R2ServiceSchema = z.object({\n provisioner: z.literal('cloudflare-r2'),\n accessKeyId: z.string().min(1),\n secretAccessKey: z.string().min(1),\n accountId: z.string().min(1),\n apiToken: z.string().min(1),\n})\n\n/** Resend 邮件服务配置 */\nconst ResendServiceSchema = z.object({\n provisioner: z.literal('resend'),\n from: z.string().email(),\n apiKey: z.string().min(1),\n})\n\n/** 阿里云短信服务配置 */\nconst AliyunSmsServiceSchema = z.object({\n provisioner: z.literal('aliyun'),\n signName: z.string().min(1),\n accessKeyId: z.string().min(1),\n accessKeySecret: z.string().min(1),\n})\n\n/** 基础设施服务配置 */\nconst ServicesConfigSchema = z.object({\n db: z.discriminatedUnion('provisioner', [NeonServiceSchema]).optional(),\n cache: z.discriminatedUnion('provisioner', [UpstashServiceSchema]).optional(),\n storage: z.discriminatedUnion('provisioner', [R2ServiceSchema]).optional(),\n email: z.discriminatedUnion('provisioner', [ResendServiceSchema]).optional(),\n sms: z.discriminatedUnion('provisioner', [AliyunSmsServiceSchema]).optional(),\n}).optional()\n\n// ─── 完整配置 Schema ───\n\n/**\n * 部署模块完整配置 Schema\n * @example\n * ```ts\n * import { DeployConfigSchema } from '@h-ai/deploy'\n * const parsed = DeployConfigSchema.safeParse({ environment: 'prod', provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!parsed.success) throw new Error('Invalid deployment configuration')\n * const baseDir = parsed.data.provider.type === 'docker-ssh' ? parsed.data.provider.remote.baseDir : undefined\n * ```\n */\nexport const DeployConfigSchema = z.object({\n /** 部署环境文件模式;dev/test/prod 或自定义模式,禁止 local/example。 */\n environment: z.string().regex(/^[a-z0-9][\\w-]*$/i).refine(value => !['local', 'example'].includes(value.toLowerCase())).optional(),\n provider: ProviderConfigSchema,\n services: ServicesConfigSchema,\n /** Docker Compose 部署参数;构建配置位于项目 hai.json.build。 */\n container: z.object({\n /** 自建 S3 服务实现;协议仍为 storage.type=s3。 */\n s3Engine: z.enum(['rustfs', 'minio']).default('rustfs'),\n }).optional(),\n})\n\n/**\n * 部署配置类型(parse 后)\n * @example\n * ```ts\n * import type { DeployConfig } from '@h-ai/deploy'\n * const config: DeployConfig = { environment: 'prod', provider: { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } } }\n * ```\n */\nexport type DeployConfig = z.infer<typeof DeployConfigSchema>\n\n/**\n * 部署配置输入类型(用户输入)\n * @example\n * ```ts\n * import type { DeployConfigInput } from '@h-ai/deploy'\n * const input: DeployConfigInput = { provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } } // 由 init 应用 remote 等默认值。\n * ```\n */\nexport type DeployConfigInput = z.input<typeof DeployConfigSchema>\n","/**\n * @h-ai/deploy — 类型定义\n *\n * 本文件定义部署模块的核心接口和类型(非配置相关)。 配置相关类型请从 deploy-config.ts 导入。\n * @module deploy-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { DeployConfig, DeployConfigInput } from './deploy-config.js'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\nconst DeployErrorInfo = {\n DEPLOY_FAILED: '001:500',\n PROJECT_CREATE_FAILED: '002:500',\n UPLOAD_FAILED: '004:500',\n AUTH_REQUIRED: '005:401',\n AUTH_FAILED: '006:401',\n PROVISION_FAILED: '007:500',\n ADAPTER_MISSING: '008:500',\n SCAN_FAILED: '009:500',\n NOT_INITIALIZED: '010:500',\n ENV_VAR_FAILED: '011:500',\n UNSUPPORTED_TYPE: '012:400',\n CONFIG_ERROR: '013:500',\n CREDENTIAL_ERROR: '014:500',\n REMOTE_CONNECT_FAILED: '017:500',\n REMOTE_COMMAND_FAILED: '018:500',\n IMAGE_TRANSFER_FAILED: '019:500',\n HEALTH_CHECK_FAILED: '020:500',\n} as const satisfies ErrorInfo\n\n/**\n *\n * @example\n * ```ts\n * import { err } from '@h-ai/core'\n * import { HaiDeployError } from '@h-ai/deploy'\n * const result = err(HaiDeployError.CONFIG_ERROR, 'Invalid deployment configuration')\n * if (!result.success && result.error.code === HaiDeployError.CONFIG_ERROR.code) {\n * process.stderr.write(result.error.message + '\\n')\n * }\n * ```\n */\nexport const HaiDeployError = core.error.buildHaiErrorsDef('deploy', DeployErrorInfo)\n\n/**\n * 部署错误接口\n *\n * 用于组合错误定义、消息与可选 cause 的描述对象;业务操作返回的 error 遵循 core.HaiError,请按 success 分支读取 code/message。\n * @example\n * ```ts\n * import type { DeployError } from '@h-ai/deploy'\n * import { HaiDeployError } from '@h-ai/deploy'\n * const detail: DeployError = { def: HaiDeployError.DEPLOY_FAILED, message: 'Deployment failed' }\n * ```\n */\nexport interface DeployError {\n /** 错误定义 */\n def: (typeof HaiDeployError)[keyof typeof HaiDeployError]\n /** 错误消息 */\n message: string\n /** 原始错误(可选) */\n cause?: unknown\n}\n\n// ─── 服务类型 ───\n\n/**\n * 基础设施服务类型\n * @example\n * ```ts\n * import type { ServiceType } from '@h-ai/deploy'\n * const service: ServiceType = 'db'\n * ```\n */\nexport type ServiceType = 'db' | 'cache' | 'storage' | 'email' | 'sms' | 'vecdb' | 'ldap'\n\n/**\n * 每项中间件的处理方式;keep 不修改配置,也不开通服务。\n * @example\n * ```ts\n * import type { MiddlewareMode } from '@h-ai/deploy'\n * const mode: MiddlewareMode = 'keep' // 复用已有服务,不修改连接配置或自动开通。\n * ```\n */\nexport type MiddlewareMode = 'default' | 'custom' | 'keep'\n\n/**\n * 扫描环境;例如 `{ environment: 'test', envDir: '/workspace/app' }`。\n * @example\n * ```ts\n * import type { DeployScanOptions } from '@h-ai/deploy'\n * const options: DeployScanOptions = { environment: 'prod', envDir: '/workspace/shop' }\n * ```\n */\nexport interface DeployScanOptions {\n /** 环境文件模式。 */\n environment?: string\n /** 环境文件目录;默认自动定位到应用或 workspace 根。 */\n envDir?: string\n}\n\n/**\n * 依赖对应的中间件;例如 IAM 的 LDAP 位于 `iam.ldap`,可处于 disabled 状态。\n * @example\n * ```ts\n * import type { MiddlewareRequirement } from '@h-ai/deploy'\n * const requirement: MiddlewareRequirement = { service: 'db', backend: 'postgresql', source: '@h-ai/reldb', configName: 'db', configPath: [], envPrefix: 'HAI_DB', config: { host: 'db', database: 'shop' } }\n * // config 可能含私有值;展示时只选择安全字段。\n * ```\n */\nexport interface MiddlewareRequirement {\n /** 中间件类别。 */\n service: ServiceType\n /** 生效后端标识。 */\n backend: string\n /** 检测来源(依赖包或配置名),用于解释为何需要此项。 */\n source: string\n /** 模块配置名。 */\n configName: string\n /** 模块配置内的路径;例如 LDAP 为 ['ldap']。 */\n configPath: string[]\n /** 约定变量前缀。 */\n envPrefix: string\n /** 生效连接配置,可能含凭据,仅用于输入默认值,不得原样输出日志。 */\n config: Record<string, unknown>\n}\n\n// ─── 扫描结果 ───\n\n/**\n * 应用扫描结果\n *\n * 由 scanner 分析应用目录后返回,描述应用的框架类型、依赖和部署需求。\n * 扫描是文件系统能力,不依赖 init,也不代表远程服务已经连通。\n * @example\n * ```ts\n * import type { ScanResult } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const result = await deploy.scan(process.cwd(), { environment: 'prod' })\n * if (!result.success) throw new Error(result.error.message)\n * const scan: ScanResult = result.data\n * const services = scan.requiredServices\n * ```\n */\nexport interface ScanResult {\n /** 调用者指定的部署目录,对应 lockfile 中的一个 importer。 */\n appDir?: string\n /** 公共环境文件目录。 */\n envDir?: string\n /** 依赖与配置共同确定的中间件详情。 */\n middlewares?: MiddlewareRequirement[]\n /** 从运行依赖图识别的 Hai 模块;peer 和开发依赖不启用模块。 */\n haiModules?: string[]\n /** 工程名称(工程根 package.json.name;缺失时报错)。 */\n appName: string\n /** 是否为 SvelteKit 项目 */\n isSvelteKit: boolean\n /** 目标平台 adapter 是否已安装(如 @sveltejs/adapter-vercel) */\n adapterInstalled: boolean\n /** 容器部署所需的 @sveltejs/adapter-node 是否已安装 */\n nodeAdapterInstalled: boolean\n /** 检测到的模块依赖需要的服务列表 */\n requiredServices: ServiceType[]\n /** 各服务检测到的后端类型(如 db→postgresql/mysql,vecdb→qdrant),用于生成匹配的 sidecar */\n serviceBackends: Partial<Record<ServiceType, string>>\n}\n\n// ─── 部署结果 ───\n\n/**\n * 部署结果\n *\n * 包含部署后的访问 URL、状态和已设置的环境变量。\n * @example\n * ```ts\n * import type { DeployResult } from '@h-ai/deploy'\n * const packaged: DeployResult = { url: '', deploymentId: 'deploy-shop-001', status: 'packaged', bundlePath: '/workspace/shop/.hai/deploy/shop-1.0.0.tar', envVarsSet: [], provider: 'docker-ssh', healthCheck: 'skipped' }\n * // packaged 只代表交付包生成;不将其展示为服务已上线。\n * ```\n */\nexport interface DeployResult {\n /** 部署后的访问 URL */\n url: string\n /** 部署 ID */\n deploymentId: string\n /** 部署状态 */\n status: 'ready' | 'packaged' | 'building' | 'error'\n /** Compose 部署 tar 的绝对路径;包含私有配置,应安全传输。 */\n bundlePath?: string\n /** 手工搬运和启动说明;仅打包不代表服务器已运行。 */\n instructions?: string\n /** 保留的有效环境变量名;packaged 状态仅表示交付计划,尚未在服务器设置。 */\n envVarsSet: string[]\n /** 部署 Provider 名称(如 vercel / docker-ssh),容器部署时返回 */\n provider?: string\n /** 健康检查结果:passed 表示 HTTP 探测成功,container-only 表示仅确认容器运行 */\n healthCheck?: 'passed' | 'container-only' | 'skipped'\n}\n\n// ─── 开通结果 ───\n\n/**\n * 基础设施开通结果\n *\n * 由 Provisioner 开通服务后返回,包含要注入到部署平台的环境变量。\n * @example\n * ```ts\n * import type { ProvisionResult } from '@h-ai/deploy'\n * const reused: ProvisionResult = { resourceStatus: 'reused', serviceType: 'db', provisionerName: 'neon', envVars: { HAI_DB_TYPE: 'postgresql' }, resourceInfo: 'Existing shop database' }\n * // envVars 可能含密码;不能直接输出。\n * ```\n */\nexport interface ProvisionResult {\n /** 本次新建或复用;凭证型服务始终为 reused */\n resourceStatus: 'created' | 'reused'\n /** 服务类型 */\n serviceType: ServiceType\n /** Provisioner 名称 */\n provisionerName: string\n /** 要注入到部署平台的环境变量 */\n envVars: Record<string, string>\n /** 资源标识信息(如项目名、数据库名等),用于日志和展示 */\n resourceInfo: string\n}\n\n/**\n * 部署失败后的安全恢复信息,不含环境变量值或原始异常。\n * @example\n * ```ts\n * import type { DeployRecoveryInfo } from '@h-ai/deploy'\n * const recovery: DeployRecoveryInfo = { projectName: 'shop', stage: 'provision', resources: [{ serviceType: 'db', provisionerName: 'neon', resourceInfo: 'shop', resourceStatus: 'unknown' }] }\n * // 先在供应商控制台核对 unknown 资源;避免重复创建计费资源。\n * ```\n */\nexport interface DeployRecoveryInfo {\n projectName: string\n stage: string\n platformProjectId?: string\n resources: Array<{\n serviceType: ServiceType\n provisionerName: string\n resourceInfo: string\n resourceStatus: 'created' | 'reused' | 'unknown'\n }>\n}\n\n/**\n * 命令失败后的已核验执行状态;远端 finished 仅指部署脚本及恢复已完成,不代表容器停止。\n * @example\n * ```ts\n * import type { DeployCommandState } from '@h-ai/deploy'\n * const state: DeployCommandState = { reason: 'timeout', localTermination: 'confirmed', remoteExecution: 'unknown', deploymentId: 'deploy-shop-001', resultFile: '/opt/hai/apps/shop/results/deploy-shop-001' }\n * if (state.remoteExecution === 'unknown') process.stderr.write('Verify the matching remote deployment result before retrying\\n')\n * ```\n */\nexport interface DeployCommandState {\n /** 失败触发原因。 */\n reason: 'timeout' | 'output' | 'input' | 'spawn' | 'exit' | 'configuration'\n /** 本地受管理树已全部退出、无法证明,或尚未启动。 */\n localTermination: 'confirmed' | 'unknown' | 'not-started'\n /** SSH 失败默认 unknown;读取匹配部署 ID 的完整终态结果后才为 finished。 */\n remoteExecution?: 'unknown' | 'finished'\n /** 本次不可变部署 ID,可与服务器结果核对。 */\n deploymentId?: string\n /** 服务器端结果文件;无凭据。 */\n resultFile?: string\n /** 匹配终态结果中的真实脚本退出码。 */\n remoteExitCode?: number\n /** 匹配终态结果中的最后阶段。 */\n remoteStage?: string\n /** 匹配终态中的恢复结果;passed 表示旧服务和 HTTP 验证通过,不包含业务数据回退。 */\n remoteRecovery?: 'not-needed' | 'passed' | 'failed' | 'stopped'\n}\n\n// ─── 部署选项 ───\n\n/**\n * 部署选项\n * 仅更新指定服务时仍受完整/部分制品与首次部署约束;bundleOnly 不触发 SSH。\n * @example\n * ```ts\n * import type { DeployAppOptions } from '@h-ai/deploy'\n * const options: DeployAppOptions = { environment: 'prod', bundleOnly: true, artifactDir: '.hai/build/docker/build-id', selectedServices: ['serv'], output: '.hai/deploy/shop.tar' }\n * ```\n */\nexport interface DeployAppOptions {\n /** 接收实际执行阶段,用于终端进度显示;不包含凭据或配置原文。 */\n onProgress?: (stage: 'packaging' | 'preflight' | 'images' | 'dependencies' | 'start' | 'https' | 'health' | 'complete') => void\n /** 只更新指定的 Compose 服务;省略时完整制品部署全部,部分制品只部署其镜像。 */\n selectedServices?: string[]\n /** 打包中间件镜像所用的本地引擎,auto 优先 Podman。 */\n runtime?: 'auto' | 'podman' | 'docker'\n /** 部署环境标识;显式指定时必须存在 .env.<environment>。 */\n environment?: string\n /** 环境文件所在目录,默认自动定位。 */\n envDir?: string\n /** 按服务或变量前缀选择处理方式;如 HAI_REACH_PROVIDERS_1 可独立于另一邮件连接。 */\n serviceModes?: Partial<Record<string, MiddlewareMode>>\n /** 是否跳过全部中间件配置与开通,默认 false;例如配置完备时设为 true。 */\n skipMiddleware?: boolean\n /** 已构建镜像目录;默认最近构建入口/锁文件目录下的 .hai/build/docker。 */\n artifactDir?: string\n /** 只生成独立交付目录(含 tar 和部署脚本),不连接 SSH;仅 docker-ssh 支持。 */\n bundleOnly?: boolean\n /** 交付包命名路径;默认在 .hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/ 中输出同名 tar 和脚本,自定义 release.tar 输出 release-<版本>/release-<版本>.tar;已有目录拒绝覆盖。 */\n output?: string\n}\n\n// ─── 凭证子功能 ───\n\n/**\n * Deploy 凭证文件操作。\n *\n * 这些方法仅操作 `~/.hai/credentials.yml`,不依赖 `deploy.init()`。\n * @example\n * ```ts\n * import type { DeployCredentialOperations } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const credentials: DeployCredentialOperations = deploy.credentials\n * const path = credentials.getPath() // 无需先 init。\n * ```\n */\nexport interface DeployCredentialOperations {\n /**\n * 获取凭证文件绝对路径。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const path = deploy.credentials.getPath() // 当前用户的全局凭证文件。\n * ```\n */\n getPath: () => string\n /**\n * 加载凭证文件并补齐 `process.env` 缺项;已有同名或父配置优先,返回文件中可识别的键名。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const loaded = deploy.credentials.load()\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const names = loaded.data // 不输出被注入的值。\n * ```\n */\n load: () => HaiResult<string[]>\n /**\n * 保存单个凭证。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = deploy.credentials.save('HAI_DEPLOY_PROVIDER_TOKEN', token)\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\n save: (key: string, value: string) => HaiResult<void>\n /**\n * 批量保存凭证。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = deploy.credentials.saveAll({ HAI_DEPLOY_PROVIDER_TOKEN: token })\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\n saveAll: (entries: Record<string, string>) => HaiResult<void>\n}\n\n// ─── 模块功能接口 ───\n\n/**\n * Deploy 模块功能接口\n *\n * 提供自动化部署的完整 API:\n * - `deploy.credentials.*()` — 凭证文件读写(不依赖 init)\n * - `deploy.init()` — 初始化(加载配置、创建 Provider 和 Provisioner)\n * - `deploy.scan()` — 扫描应用依赖(纯文件系统能力,不依赖 init)\n * - `deploy.provisionAll()` — 开通所有已配置的基础设施\n * - `deploy.deployApp()` — 完整部署流程\n * - `deploy.close()` — 关闭模块\n * scan 与 credentials 不需要 init;部署与开通遵循 init → 检查结果 → use → finally close。close 返回 Promise<void>,不伪造 HaiResult。\n * @example\n * ```ts\n * import type { DeployFunctions } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const operations: DeployFunctions = deploy\n * const scan = await operations.scan(process.cwd())\n * if (!scan.success) throw new Error(scan.error.message)\n * const required = scan.data.requiredServices\n * ```\n */\nexport interface DeployFunctions {\n /** 全局部署凭证文件操作。 */\n readonly credentials: DeployCredentialOperations\n /**\n * 初始化模块(加载配置、创建 Provider 和 Provisioner 实例)\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * const ready = deploy.isInitialized\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n init: (config: DeployConfigInput) => Promise<HaiResult<void>>\n /**\n * 关闭模块\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * const provider = deploy.config?.provider.type\n * }\n * finally {\n * await deploy.close() // Promise<void>;不检查不存在的 success 字段。\n * }\n * ```\n */\n close: () => Promise<void>\n /** 当前配置 */\n readonly config: DeployConfig | null\n /** 是否已初始化 */\n readonly isInitialized: boolean\n\n /**\n * 扫描应用目录,检测依赖和所需服务。\n *\n * 这是纯文件系统分析能力,不依赖云端认证状态,可在 `deploy.init()` 之前调用。\n *\n * @param appDir - 应用根目录路径\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const scanned = await deploy.scan(process.cwd(), { environment: 'prod' })\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const services = scanned.data.requiredServices // 无需 init。\n * ```\n */\n scan: (appDir: string, options?: DeployScanOptions) => Promise<HaiResult<ScanResult>>\n\n /**\n * 对所有已配置的 Provisioner 执行基础设施开通\n *\n * @param projectName - 用于资源命名的项目名\n * @returns 所有 Provisioner 的结果列表\n * @example\n * ```ts\n * import { deploy, getDeployRecovery } from '@h-ai/deploy'\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_DB_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_DB_APIKEY privately')\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } }, services: { db: { provisioner: 'neon', apiKey } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 会访问真实云服务并可能新建资源。\n * const result = await deploy.provisionAll('shop', ['db'])\n * if (!result.success) {\n * const recovery = getDeployRecovery(result.error)\n * if (recovery?.resources.some(resource => resource.resourceStatus === 'unknown')) {\n * process.stderr.write('Verify unknown resources at the provider before retrying\\n')\n * }\n * throw new Error(result.error.message)\n * }\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n provisionAll: (projectName: string, services?: ServiceType[]) => Promise<HaiResult<ProvisionResult[]>>\n\n /**\n * 部署已有构建产物(环境和中间件 → 打包 → 上传/启动);不会调用构建命令。\n *\n * @param appDir - 应用根目录路径\n * @param options - 部署选项\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 当前项目必须已有构建镜像清单与生产环境配置。\n * const result = await deploy.deployApp(process.cwd(), { environment: 'prod', bundleOnly: true })\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.status // packaged 不代表线上运行。\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n deployApp: (appDir: string, options?: DeployAppOptions) => Promise<HaiResult<DeployResult>>\n}\n","/** 部署环境的加载和持久化;公开环境文件不保存真实凭据。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { chmodSync, existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { extname, join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { parseEnv } from 'node:util'\nimport { core, err, ok } from '@h-ai/core'\nimport { LineCounter, parse, parseDocument } from 'yaml'\nimport { ProviderConfigSchema } from './deploy-config.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\n/**\n * 部署环境快照;例如 prod 的 targetValues 只来自 `.env.prod`,不包含基础/私有覆盖。\n * @example\n * ```ts\n * import type { DeploymentEnvironment } from '@h-ai/deploy'\n * const environment: DeploymentEnvironment = { environment: 'prod', envDir: '/workspace/shop', values: { HAI_DB_TYPE: 'postgresql' }, targetValues: { HAI_DB_TYPE: 'postgresql' } }\n * // values 可能还含私有凭据,不能整体写入日志。\n * ```\n */\nexport interface DeploymentEnvironment {\n /** 文件模式(dev/test/prod 或其他合法模式名)。 */\n environment: string\n /** 环境文件的绝对目录。 */\n envDir: string\n /** 合并后的部署变量,可能含私有值,不得直接记录日志。 */\n values: Record<string, string>\n /** 仅目标环境文件显式声明的变量,用于判断能否“保持不变”。 */\n targetValues: Record<string, string>\n}\n\n/** 与 Core 一致,普通字符串如 CORS 的 `*` 不能因 YAML 标量解析失败而使配置加载失败。 */\nfunction environmentValue(value: string): unknown {\n try {\n return parse(value) ?? value\n }\n catch {\n return value\n }\n}\n\nconst SSH_PREFIX = 'HAI_DEPLOY_PROVIDER_SSH'\nconst sshProvider = ProviderConfigSchema.options.find(provider => 'ssh' in provider.shape)\n// 从同一 Schema 读取已知键;不把任意环境变量扩成配置字段。\nconst sshFields = new Map(sshProvider && 'ssh' in sshProvider.shape\n ? Object.keys(sshProvider.shape.ssh.unwrap().shape).map(name => [name.toUpperCase(), name])\n : [])\nconst numericSshFields = new Set(['PORT', 'CONNECTTIMEOUTSECONDS', 'STRICTHOSTKEYCHECKING'])\n\n/** 在已解析的结构上覆盖;部署父对象仍允许同来源、更具体的 SSH 字段覆盖。 */\nfunction resolveConfig(value: unknown, prefix: string, env: Record<string, string | undefined>, deployment = false, literal = false): unknown {\n const sshField = prefix.startsWith(`${SSH_PREFIX}_`) ? prefix.slice(SSH_PREFIX.length + 1) : undefined\n const textSshField = sshField !== undefined && sshFields.has(sshField) && !numericSshFields.has(sshField)\n if (env[prefix] !== undefined) {\n if (deployment && textSshField)\n return env[prefix]\n if (!deployment)\n return environmentValue(env[prefix])\n value = environmentValue(env[prefix])\n // 环境 JSON 中的密码等文本已经是字面量,不能二次展开其中的 ${...}。\n literal = true\n }\n if (Array.isArray(value))\n return value.map((item, index) => resolveConfig(item, `${prefix}_${index}`, env, deployment, literal))\n if (value && typeof value === 'object') {\n const input: Record<string, unknown> = { ...value }\n if (deployment) {\n const hasSshInput = env[SSH_PREFIX] !== undefined || [...sshFields.keys()].some(field => env[`${SSH_PREFIX}_${field}`] !== undefined)\n if (hasSshInput && prefix === 'HAI_DEPLOY' && input.provider === undefined)\n input.provider = {}\n if (hasSshInput && prefix === 'HAI_DEPLOY_PROVIDER' && input.ssh === undefined)\n input.ssh = {}\n if (prefix === SSH_PREFIX) {\n for (const [field, name] of sshFields) {\n if (env[`${SSH_PREFIX}_${field}`] !== undefined && !(name in input))\n input[name] = undefined\n }\n }\n }\n return Object.fromEntries(Object.entries(input).map(([key, nested]) => [key, resolveConfig(nested, `${prefix}_${key.toUpperCase()}`, env, deployment, literal)]))\n }\n if (typeof value !== 'string')\n return value\n if (literal)\n return value\n const resolved = value.replace(/\\$\\{([^:}]+)(?::([^}]*))?\\}/g, (_match, name: string, fallback?: string) => env[name] ?? fallback ?? '')\n return /^\\$\\{[^}]+\\}$/.test(value) && !textSshField ? environmentValue(resolved) : resolved\n}\n\n/** 读取单层 dotenv;所有错误由调用边界转换为脱敏 HaiResult。 */\nfunction environmentFile(path: string): Record<string, string> {\n const values: Record<string, string> = {}\n if (existsSync(path)) {\n for (const [name, value] of Object.entries(parseEnv(readFileSync(path, 'utf8')))) {\n if (value !== undefined)\n values[name] = value\n }\n }\n return values\n}\n\n/**\n * 按来源归并环境变量;HAI 高层父配置清除旧叶,同层按父→叶处理。\n * @param layers - 从低到高优先级的环境来源。\n * @param prefix - 可选变量前缀,仅归并该模块。\n * @returns 归并后的字面量环境变量,可能包含秘密。\n * @example 模块内部上下文\n * ```ts\n * const env = mergeEnvironmentLayers([{ HAI_CACHE_TYPE: 'memory' }, { HAI_CACHE: '{\"type\":\"redis\"}' }])\n * ```\n */\nexport function mergeEnvironmentLayers(layers: Array<Record<string, string | undefined>>, prefix?: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const layer of layers) {\n const names = Object.keys(layer).filter(name => !prefix || name === prefix || name.startsWith(`${prefix}_`)).sort((left, right) => left.length - right.length)\n for (const name of names) {\n const value = layer[name]\n if (value === undefined)\n continue\n if (name.startsWith('HAI_')) {\n for (const previous of Object.keys(result)) {\n if (previous.startsWith(`${name}_`))\n delete result[previous]\n }\n }\n result[name] = value\n }\n }\n return result\n}\n\n/**\n * 只描述变量名与来源,不把初始密码等变量值带入交付说明。\n * @param directory - 打包源工程的环境文件目录。\n * @param environment - 本次交付选择的环境名。\n * @param values - 已解析的有效环境变量,可能包含私密值。\n * @param names - 需要在交付说明中解释的变量名。\n * @returns 已配置变量的名称及来源,不含变量值。\n * @example 模块内部上下文\n * ```ts\n * const environment = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (environment.success) {\n * const sources = describeDeploymentVariableSources(environment.data.envDir, 'prod', environment.data.values, ['HAI_CONFIG_ADMIN_PASSWORD'])\n * // sources 仅包含变量名和来源,可以写入交付说明。\n * }\n * ```\n */\nexport function describeDeploymentVariableSources(directory: string, environment: string, values: Record<string, string>, names: readonly string[]): string {\n const files = [`.env.${environment}.local`, '.env.local', `.env.${environment}`, '.env']\n .map(name => ({ path: join(directory, name), values: environmentFile(join(directory, name)) }))\n return names.filter(name => values[name]).map((name) => {\n const source = process.env[name] !== undefined ? 'process.env' : files.find(file => Object.hasOwn(file.values, name))?.path\n return `${name}: ${source ?? '.env.runtime'}`\n }).join('\\n')\n}\n\n/**\n * 按部署环境解析配置;未选择的可选 Provisioner 缺少凭据时保留空值,选择完成后由 Schema 校验。\n * hai.json 只读取对应的根分区;运行时模块继续读取 YAML。不修改 core 缓存或进程变量。\n * @param name - 模块配置名,例如 deploy/db/iam\n * @param path - hai.json 或运行时 YAML 文件的绝对路径\n * @param values - 已加载的目标环境变量\n * @returns 配置对象;解析错误已脱敏\n * @example\n * ```ts\n * import { loadDeploymentConfig, loadDeploymentEnvironment } from '@h-ai/deploy'\n * const environment = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!environment.success) throw new Error(environment.error.message)\n * const config = loadDeploymentConfig('deploy', `${process.cwd()}/hai.json`, environment.data.values)\n * if (!config.success) throw new Error(config.error.message)\n * // 返回对象仍需经 DeployConfigSchema 或 deploy.init 验证。\n * ```\n */\nexport function loadDeploymentConfig(name: string, path: string, values: Record<string, string | undefined>): HaiResult<Record<string, unknown>> {\n try {\n const content = readFileSync(path, 'utf8')\n let input: unknown\n if (extname(path).toLowerCase() === '.json') {\n try {\n const project: unknown = JSON.parse(content)\n input = project && typeof project === 'object' && !Array.isArray(project) ? (project as Record<string, unknown>)[name] : undefined\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n }\n if (!input || typeof input !== 'object' || Array.isArray(input))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n }\n else {\n const lineCounter = new LineCounter()\n const document = parseDocument(content, { lineCounter, prettyErrors: false })\n if (document.errors.length)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: String(lineCounter.linePos(document.errors[0]!.pos[0]).line) } }))\n input = document.toJS()\n }\n const config = resolveConfig(input, `HAI_${name.toUpperCase()}`, values, name === 'deploy')\n if (config !== null && (typeof config !== 'object' || Array.isArray(config)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n return ok(config && typeof config === 'object' && !Array.isArray(config) ? config as Record<string, unknown> : {})\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileUnreadable', { params: { path } }))\n }\n}\n\n/**\n * 加载部署环境;指定环境文件缺失时返回错误并要求用户创建。\n * 部署目标按进程 > 模式私有 > 模式公共 > 旧全局私有 > 基础归并。\n * 其它模块保留进程 > 模式私有 > 旧全局私有 > 模式公共 > 基础;targetValues 仅记录模式公共项。\n * @param options - 模式、环境目录与是否强制存在目标文件\n * @param options.environment - dev/test/prod 或自定义模式\n * @param options.envDir - 环境文件所在目录\n * @param options.requireFile - 默认 true;扫描无显式环境时可只读取已有基础文件\n * @returns 环境快照,可能包含私有值,不得直接输出\n * @example\n * ```ts\n * import { loadDeploymentEnvironment } from '@h-ai/deploy'\n * const loaded = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const explicitlyConfigured = loaded.data.targetValues.HAI_DB_TYPE\n * ```\n */\nexport function loadDeploymentEnvironment(options: { environment: string, envDir: string, requireFile?: boolean }): HaiResult<DeploymentEnvironment> {\n const environment = options.environment === 'production' ? 'prod' : options.environment === 'development' ? 'dev' : options.environment\n if (!/^[a-z0-9][\\w-]*$/i.test(environment) || ['local', 'example'].includes(environment.toLowerCase()))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_invalidEnvironment'))\n const envDir = resolve(options.envDir)\n const target = join(envDir, `.env.${environment}`)\n if (options.requireFile !== false && !existsSync(target))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_environmentMissing', { params: { path: target } }))\n const loaded = core.config.loadEnvFiles({ mode: environment, envDir })\n if (!loaded.success)\n return loaded\n try {\n const base = environmentFile(join(envDir, '.env'))\n const globalPrivate = environmentFile(join(envDir, '.env.local'))\n const selected = environmentFile(target)\n const modePrivate = environmentFile(join(envDir, `.env.${environment}.local`))\n const values = { ...loaded.data, ...modePrivate }\n // Core 已处理原三层;模式私有层也必须继续服从显式进程覆盖。\n for (const name of Object.keys(values)) {\n if (process.env[name] !== undefined)\n values[name] = process.env[name]\n }\n // 只传递应用配置和显式声明的运行变量,不上传整个调用者进程环境。\n for (const [name, value] of Object.entries(process.env)) {\n if (/^(?:HAI_|PUBLIC_|VITE_)/.test(name) && value !== undefined)\n values[name] = value\n }\n for (const name of Object.keys(values)) {\n if (name === 'HAI_DEPLOY' || name.startsWith('HAI_DEPLOY_'))\n delete values[name]\n }\n Object.assign(values, mergeEnvironmentLayers([base, globalPrivate, selected, modePrivate, process.env], 'HAI_DEPLOY'))\n values.HAI_DEPLOY_ENVIRONMENT = environment\n values.HAI_CORE_ENV ??= environment === 'prod' ? 'production' : environment === 'dev' ? 'development' : environment === 'test' ? 'test' : 'staging'\n return ok({ environment, envDir, values, targetValues: selected })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_environmentReadFailed'))\n }\n}\n\n/** 判断值是否包含凭据;连接 URL 和 JSON 配置需要递归检查。 */\nfunction isSecret(name: string, value: string): boolean {\n if (/PASSWORD|SECRET|TOKEN|APIKEY|PRIVATEKEY|ACCESSKEY|AUTHORIZATION/i.test(name.replace(/[^a-z0-9]/gi, '')) || /(?:^|_)PASS$/i.test(name) || value.includes('PRIVATE KEY'))\n return true\n try {\n const url = new URL(value)\n if (url.username || url.password || [...url.searchParams.keys()].some(key => /password|secret|token|key|authorization/i.test(key)))\n return true\n }\n catch { /* 非 URL 配置继续按结构检查。 */ }\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n return Object.entries(parsed).some(([key, nested]) => isSecret(key, typeof nested === 'string' ? nested : JSON.stringify(nested)))\n }\n catch { /* 普通字符串无需 JSON 处理。 */ }\n return false\n}\n\n/** 将 JSON 中的凭据剥离,公共文件仍保留可审查的后端/连接结构。 */\nfunction publicConfig(value: unknown): unknown {\n if (Array.isArray(value))\n return value.map(publicConfig)\n if (value && typeof value === 'object')\n return Object.fromEntries(Object.entries(value).filter(([name, item]) => !isSecret(name, typeof item === 'string' ? item : '')).map(([name, item]) => [name, publicConfig(item)]))\n return value\n}\n\n/** dotenv 引号保留空格、注释符、美元符号和 JSON;非法换行键由调用边界拒绝。 */\nfunction quoteEnv(value: string): string {\n // JSON 内用 Unicode 转义表示单引号,dotenv 单引号即可无损保存复杂密码。\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n return `'${JSON.stringify(parsed).replaceAll('\\'', '\\\\u0027')}'`\n }\n catch { /* 标量按 dotenv 原生引号规则处理。 */ }\n if (!value.includes('\\''))\n return `'${value}'`\n if (!value.includes('\"'))\n return `\"${value}\"`\n if (!value.includes('`'))\n return `\\`${value}\\``\n if (!/[\\r\\n#]/.test(value))\n return value\n throw new Error('Unsupported dotenv value')\n}\n\n/** 按原有行更新键,保留注释与其他配置;更新私有文件时要求权限 600。 */\nfunction updateFile(path: string, values: Record<string, string>, privateFile: boolean): void {\n let content = existsSync(path) ? readFileSync(path, 'utf8') : '# Local private deployment configuration; do not commit.\\n'\n for (const [name, value] of Object.entries(values)) {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name))\n throw new Error('Invalid environment variable name')\n const line = `${name}=${quoteEnv(value)}`\n // parseEnv 支持多行引号;替换时一起消费原值,避免遗留秘密片段。\n const pattern = new RegExp(`^(?:export\\\\s+)?${name}\\\\s*=\\\\s*(?:'[^']*'|\"[^\"]*\"|\\`[^\\`]*\\`|[^\\\\r\\\\n]*)[^\\\\r\\\\n]*`, 'gm')\n if (pattern.test(content))\n content = content.replace(pattern, () => line)\n else\n content = `${content.trimEnd()}\\n${line}\\n`\n }\n writeFileSync(path, content, { mode: privateFile ? 0o600 : 0o644 })\n if (privateFile)\n chmodSync(path, 0o600)\n}\n\n/** 明确修改的公共项必须清掉同名旧私有覆盖,避免重新加载后仍用旧后端。 */\nfunction removeOverrides(path: string, names: string[], privateFile = true): void {\n if (!existsSync(path) || names.length === 0)\n return\n let content = readFileSync(path, 'utf8')\n for (const name of names)\n content = content.replace(new RegExp(`^(?:export\\\\s+)?${name}\\\\s*=\\\\s*(?:'[^']*'|\"[^\"]*\"|\\`[^\\`]*\\`|[^\\\\r\\\\n]*)[^\\\\r\\\\n]*(?:\\\\r?\\\\n|$)`, 'gm'), '')\n writeFileSync(path, content, { mode: privateFile ? 0o600 : 0o644 })\n chmodSync(path, privateFile ? 0o600 : 0o644)\n}\n\n/**\n * 保存部署变量:公共值写目标环境文件,凭据写 `.env.<environment>.local`;旧共享私有文件不删除。\n * 返回实际写入的变量名,调用者只展示名称或脱敏值。\n * @param environment - 已加载的目标环境快照\n * @param values - 需要更新的变量;未提供的项保持原状\n * @param options - private 为 true 时所有值只保存在本机;适用于 SSH 地址、端口及密钥路径\n * @param options.private - 是否将全部值保存到选中模式的私有文件\n * @returns 已保存的变量名或脱敏错误\n * @example\n * ```ts\n * import { loadDeploymentEnvironment, saveDeploymentEnvironment } from '@h-ai/deploy'\n * const loaded = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const saved = saveDeploymentEnvironment(loaded.data, { HAI_DB_HOST: 'db' })\n * if (!saved.success) throw new Error(saved.error.message)\n * // 密钥应以 { private: true } 写入被忽略的 .env.prod.local,不能放公共环境文件。\n * ```\n */\nexport function saveDeploymentEnvironment(environment: DeploymentEnvironment, values: Record<string, string>, options: { private?: boolean } = {}): HaiResult<string[]> {\n try {\n const shared: Record<string, string> = {}\n const privateValues: Record<string, string> = {}\n for (const [name, value] of Object.entries(values)) {\n if (options.private) {\n privateValues[name] = value\n }\n else if (isSecret(name, value)) {\n privateValues[name] = value\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n shared[name] = JSON.stringify(publicConfig(parsed))\n }\n catch { /* 标量秘密仅写私有文件。 */ }\n }\n else {\n shared[name] = value\n }\n }\n const privatePath = join(environment.envDir, `.env.${environment.environment}.local`)\n const globalPrivate = environmentFile(join(environment.envDir, '.env.local'))\n // 非部署模块保留旧 private 优先级;显式换后端时在当前模式遮盖旧值,不破坏其它环境的 fallback。\n for (const [name, value] of Object.entries(shared)) {\n if (!(name in privateValues) && globalPrivate[name] !== undefined && name !== 'HAI_DEPLOY' && !name.startsWith('HAI_DEPLOY_'))\n privateValues[name] = value\n }\n if (Object.keys(shared).length)\n updateFile(join(environment.envDir, `.env.${environment.environment}`), shared, false)\n if (Object.keys(privateValues).length)\n updateFile(privatePath, privateValues, true)\n removeOverrides(join(environment.envDir, `.env.${environment.environment}`), Object.keys(privateValues).filter(name => !(name in shared)), false)\n removeOverrides(privatePath, Object.keys(shared).filter(name => !(name in privateValues)))\n if (Object.keys(privateValues).length) {\n const ignorePath = join(environment.envDir, '.gitignore')\n const ignore = existsSync(ignorePath) ? readFileSync(ignorePath, 'utf8') : ''\n const missing = ['.env.local', '.env.*.local', '.hai/deploy/'].filter(line => !ignore.split(/\\r?\\n/).includes(line))\n if (missing.length)\n writeFileSync(ignorePath, `${ignore.trimEnd()}\\n${missing.join('\\n')}\\n`)\n }\n return ok(Object.keys(values))\n }\n catch {\n return err(HaiDeployError.ENV_VAR_FAILED, deployM('deploy_environmentWriteFailed'))\n }\n}\n","/**\n * @h-ai/deploy — 部署辅助函数\n *\n * 包含已有产物目录解析等与部署流程相关的辅助操作。 从 deploy-main.ts 中提取,遵循 main 仅做生命周期管理的规范。\n * @module deploy-functions\n */\n\nimport type { DeployAppOptions, ScanResult, ServiceType } from './deploy-types.js'\nimport { existsSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { deployM } from './deploy-i18n.js'\n\n/**\n * 将工程根 package.json.name 归一化为镜像与部署资源共用的身份;移除 scope、转小写并合并非法字符。\n * @throws Error - 名称为空或归一化后不含字母数字。\n * @param name - 工程根 package.json.name。\n * @returns 可用于 OCI 镜像和 Compose 资源的工程名。\n * @example\n * ```ts\n * import { normalizeProjectName } from '@h-ai/deploy'\n * const name = normalizeProjectName('@shop/orders')\n * ```\n */\nexport function normalizeProjectName(name: string): string {\n const normalized = name.trim().replace(/^@[^/]+\\//, '').toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '')\n if (!normalized)\n throw new Error(deployM('deploy_projectNameRequired'))\n return normalized\n}\n\n/**\n * 定位工程根;API workspace 的环境文件可在服务包,构建与部署缓存仍位于工程根。\n * 只定位已约定的构建入口/锁文件,不从目录布局推断应用或中间件依赖。\n * 从目标包向上查找构建入口或锁文件;返回目录不表示清单已存在或通过校验。\n * @param appDir - 部署目标应用目录。\n * @returns 最近的工程入口目录;未找到入口时返回应用目录的绝对路径。\n * @example 模块内部上下文\n * ```ts\n * const project = resolveProjectDirectory('/workspace/shop/apps/shop-serv')\n * ```\n */\nexport function resolveProjectDirectory(appDir: string): string {\n let directory = resolve(appDir)\n while (true) {\n if (existsSync(join(directory, 'hai.json')) || existsSync(join(directory, 'pnpm-lock.yaml')))\n return directory\n const parent = dirname(directory)\n if (parent === directory)\n return resolve(appDir)\n directory = parent\n }\n}\n\n/**\n * 定位工程根的构建缓存目录;环境文件留在服务包时也沿用同一工程根。\n * @param appDir - 部署目标应用目录。\n * @returns 约定的 .hai/build/docker 目录;不保证其中制品存在或通过校验。\n * @example 模块内部上下文\n * ```ts\n * const directory = resolveArtifactDirectory('/workspace/shop/apps/shop-serv')\n * ```\n */\nexport function resolveArtifactDirectory(appDir: string): string {\n return join(resolveProjectDirectory(appDir), '.hai/build/docker')\n}\n\n/**\n * 判断同类连接中是否有默认配置项;具体变量前缀优先于服务类别,未指定时默认处理。\n * @param scan - 依据实际依赖图及环境得到的扫描结果。\n * @param service - 待判断的中间件类别。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 同类连接中存在采用 default 策略的项时为 true。\n * @example 模块内部上下文\n * ```ts\n * const scan: ScanResult = { appName: 'shop', isSvelteKit: false, adapterInstalled: false, nodeAdapterInstalled: false, requiredServices: [], serviceBackends: {} }\n * const enabled = usesDefaultMiddleware(scan, 'db', { serviceModes: { db: 'keep' } }) // false\n * ```\n */\nexport function usesDefaultMiddleware(scan: ScanResult, service: ServiceType, options?: DeployAppOptions): boolean {\n const requirements = scan.middlewares?.filter(item => item.service === service) ?? []\n return requirements.length\n ? requirements.some(item => (options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.[service] ?? 'default') === 'default')\n : (options?.serviceModes?.[service] ?? 'default') === 'default'\n}\n\n/**\n * 解析构建产物目录\n * @param appDir - 应用根目录\n * @param providerType - Provider 类型\n * @returns 产物目录路径\n * @example 模块内部上下文\n * ```ts\n * const directory = resolveOutputDir('/workspace/shop', 'vercel') // /workspace/shop/.vercel/output\n * ```\n */\nexport function resolveOutputDir(appDir: string, providerType: string): string {\n switch (providerType) {\n case 'vercel':\n return join(appDir, '.vercel', 'output')\n default:\n return join(appDir, 'build')\n }\n}\n","/**\n * @h-ai/deploy — 凭证管理\n *\n * 管理全局凭证文件 `~/.hai/credentials.yml`。\n * 这些 helper 由 `deploy.credentials.*` 对外暴露,供 CLI 在加载项目 `hai.json` 的部署配置\n * 之前注入 `HAI_DEPLOY_*` 环境变量。\n * @module deploy-credentials\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { core, err, ok } from '@h-ai/core'\nimport { parse, stringify } from 'yaml'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'credentials' })\n\n/** 仅允许写入 deploy 模块自有的环境变量前缀,避免把任意 YAML key 注入 process.env。 */\nconst DEPLOY_CREDENTIAL_KEY_PATTERN = /^HAI_DEPLOY_[A-Z0-9_]+$/\n\n// ─── 内部工具 ───\n\n/** 校验凭证键名是否属于 deploy 模块。 */\nfunction isAllowedCredentialKey(key: string): boolean {\n return DEPLOY_CREDENTIAL_KEY_PATTERN.test(key)\n}\n\n/**\n * 标准化凭证键值对。\n *\n * 仅保留 `HAI_DEPLOY_*` 键,且值必须是可安全序列化为字符串的标量。\n */\nfunction normalizeCredentialEntries(entries: Record<string, unknown>): Record<string, string> {\n const normalized: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(entries)) {\n if (!isAllowedCredentialKey(key)) {\n logger.warn('Ignoring unsupported deploy credential key', { key })\n continue\n }\n\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n normalized[key] = String(value)\n continue\n }\n\n logger.warn('Ignoring deploy credential with non-scalar value', { key })\n }\n\n return normalized\n}\n\n/** 在写入前校验单个凭证键名。 */\nfunction assertAllowedCredentialKey(key: string): void {\n if (!isAllowedCredentialKey(key)) {\n throw new Error(deployM('deploy_credentialInvalidKey', { params: { key } }))\n }\n}\n\n/** 在写入前校验批量凭证键名。 */\nfunction assertAllowedCredentialEntries(entries: Record<string, string>): void {\n for (const key of Object.keys(entries)) {\n assertAllowedCredentialKey(key)\n }\n}\n\n/**\n * 获取凭证文件路径\n * @returns `~/.hai/credentials.yml` 的绝对路径\n * @example 模块内部上下文\n * ```ts\n * const path = getCredentialsPath() // 当前用户 ~/.hai/credentials.yml,不含凭据内容。\n * ```\n */\nexport function getCredentialsPath(): string {\n return join(homedir(), '.hai', 'credentials.yml')\n}\n\n/**\n * 确保凭证目录存在\n *\n * @param filePath - 凭证文件路径\n */\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * 读取凭证文件内容\n *\n * @returns 解析后的键值对,文件不存在时返回空对象\n */\nfunction readCredentialsFile(): Record<string, string> {\n const filePath = getCredentialsPath()\n if (!existsSync(filePath)) {\n return {}\n }\n const content = readFileSync(filePath, 'utf-8')\n const parsed = parse(content)\n if (parsed === null || parsed === undefined || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return {}\n }\n return normalizeCredentialEntries(parsed as Record<string, unknown>)\n}\n\n/**\n * 写入凭证文件\n *\n * @param data - 凭证键值对\n */\nfunction writeCredentialsFile(data: Record<string, string>): void {\n const filePath = getCredentialsPath()\n ensureDir(filePath)\n const header = '# Managed by hai cli - do not edit manually\\n'\n const content = header + stringify(data)\n writeFileSync(filePath, content, { encoding: 'utf-8', mode: 0o600 })\n}\n\n// ─── 公共 API ───\n\n/**\n * 加载全局凭证文件并注入到 process.env\n *\n * 读取 `~/.hai/credentials.yml` 中的所有键值对,\n * 仅为尚未设置的键注入默认值;已有父配置也优先于全局文件的细分键,\n * 使后续 core 配置加载时自动解析 `${HAI_DEPLOY_*}` 变量。\n * @returns 返回文件中可识别的键名,包括被当前配置遮盖而未注入的键。\n * @example 模块内部上下文\n * ```ts\n * const loaded = loadCredentials()\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const credentialNames = loaded.data // 仅文件键名;已有 process.env 值优先。\n * ```\n */\nexport function loadCredentials(): HaiResult<string[]> {\n try {\n const data = readCredentialsFile()\n const keys = Object.keys(data)\n const configured = Object.keys(process.env).filter(key => (key === 'HAI_DEPLOY' || isAllowedCredentialKey(key)) && process.env[key] !== undefined)\n for (const key of keys) {\n if (!configured.some(name => key === name || key.startsWith(`${name}_`)))\n process.env[key] = String(data[key])\n }\n logger.debug('Credentials loaded', { count: keys.length })\n return ok(keys)\n }\n catch (error) {\n logger.error('Failed to load credentials', { error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n/**\n * 保存单个凭证到全局凭证文件\n *\n * 读取已有凭证 → 合并新凭证 → 写回文件。已有同名 key 会被覆盖。\n * 会写入当前用户的全局凭证文件;仅允许 HAI_DEPLOY_ 前缀。\n * @param key - 环境变量名(如 HAI_DEPLOY_PROVIDER_TOKEN)\n * @param value - 凭证值\n * @returns 已保存时成功;键名、文件或权限处理失败时为错误结果。\n * @example 模块内部上下文\n * ```ts\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = saveCredential('HAI_DEPLOY_PROVIDER_TOKEN', token)\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\nexport function saveCredential(key: string, value: string): HaiResult<void> {\n try {\n assertAllowedCredentialKey(key)\n const data = readCredentialsFile()\n data[key] = value\n writeCredentialsFile(data)\n process.env[key] = value\n logger.debug('Credential saved', { key })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Failed to save credential', { key, error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n/**\n * 批量保存凭证到全局凭证文件\n * @param entries - 凭证键值对\n * @returns 已保存时成功;校验失败不会注入任意键名。\n * @example 模块内部上下文\n * ```ts\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = saveCredentials({ HAI_DEPLOY_PROVIDER_TOKEN: token })\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\nexport function saveCredentials(entries: Record<string, string>): HaiResult<void> {\n try {\n assertAllowedCredentialEntries(entries)\n const data = readCredentialsFile()\n for (const [key, value] of Object.entries(entries)) {\n data[key] = value\n process.env[key] = value\n }\n writeCredentialsFile(data)\n logger.debug('Credentials saved', { count: Object.keys(entries).length })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Failed to save credentials', { error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n","/** 自建与云开通共用的配置合并;业务选项保留,连接选择器由实际开通结果定稿。 */\nimport type { MiddlewareRequirement, ServiceType } from './deploy-types.js'\n\n/** 旧地址、认证与连接模式不能覆盖新服务;其余同后端配置继续生效。 */\nconst connectionFields: Partial<Record<ServiceType, readonly string[]>> = {\n db: ['url', 'host', 'port', 'database', 'user', 'password', 'ssl'],\n cache: ['url', 'host', 'port', 'password', 'cluster', 'sentinel', 'tls'],\n storage: ['endpoint', 'bucket', 'region', 'accessKeyId', 'secretAccessKey', 'forcePathStyle', 'createBucket'],\n vecdb: ['url', 'host', 'port', 'database', 'user', 'password', 'apiKey', 'path', 'serverCommand', 'startupTimeout'],\n ldap: ['url', 'bindDn', 'bindPassword', 'searchBase', 'useTls'],\n email: ['host', 'port', 'secure', 'user', 'pass'],\n}\n\n/**\n * 将有效业务配置带入托管连接;切换后端时不迁移旧后端字段。\n * @param requirement - 扫描得到的最终有效中间件配置。\n * @param supplied - 自建或云开通生成的实际连接。\n * @returns 完整配置,可能含凭据,不能直接输出到日志。\n * @example 模块内部上下文\n * ```ts\n * const requirement: MiddlewareRequirement = { service: 'storage', backend: 's3', source: 'storage', configName: 'storage', configPath: [], envPrefix: 'HAI_STORAGE', config: { publicEndpoint: 'https://app.example.com/files' } }\n * const storage = mergeManagedMiddlewareConfig(requirement, { type: 's3', endpoint: 'http://storage:9000', bucket: 'hai' })\n * ```\n */\nexport function mergeManagedMiddlewareConfig(requirement: MiddlewareRequirement | undefined, supplied: Record<string, unknown>): Record<string, unknown> {\n if (!requirement || (requirement.service !== 'ldap' && requirement.backend !== supplied.type))\n return supplied\n const configured = { ...requirement.config }\n for (const field of connectionFields[requirement.service] ?? [])\n delete configured[field]\n const merged = { ...configured, ...supplied }\n // Redis URL 的数据库编号优先于独立 db 字段;保留选项时必须同步真实连接地址。\n if (requirement.service === 'cache' && typeof configured.db === 'number' && typeof supplied.url === 'string') {\n const url = new URL(supplied.url)\n if (configured.db !== 0 || (url.pathname !== '' && url.pathname !== '/')) {\n url.pathname = String(configured.db)\n merged.url = url.toString()\n }\n }\n return merged\n}\n","import type { HaiError, HaiResult } from '@h-ai/core'\nimport type { DeployCommandState, DeployRecoveryInfo } from './deploy-types.js'\nimport { err } from '@h-ai/core'\nimport { z } from 'zod'\nimport { deployM } from './deploy-i18n.js'\n\nconst RecoverySchema = z.object({\n projectName: z.string(),\n stage: z.string(),\n platformProjectId: z.string().optional(),\n resources: z.array(z.object({\n serviceType: z.enum(['db', 'cache', 'storage', 'email', 'sms']),\n provisionerName: z.string(),\n resourceInfo: z.string(),\n resourceStatus: z.enum(['created', 'reused', 'unknown']),\n })),\n})\n\nconst CommandStateSchema = z.object({\n reason: z.enum(['timeout', 'output', 'input', 'spawn', 'exit', 'configuration']),\n localTermination: z.enum(['confirmed', 'unknown', 'not-started']),\n remoteExecution: z.enum(['unknown', 'finished']).optional(),\n deploymentId: z.string().optional(),\n resultFile: z.string().optional(),\n remoteExitCode: z.number().int().optional(),\n remoteStage: z.string().optional(),\n remoteRecovery: z.enum(['not-needed', 'passed', 'failed', 'stopped']).optional(),\n})\n\n/**\n * 读取命令失败的安全状态;不把本地 SSH 退出解释为远端停止。\n * @param error - 部署错误\n * @returns 通过结构校验的命令状态,或 undefined\n * @example\n * ```ts\n * import { getDeployCommandState, HaiDeployError } from '@h-ai/deploy'\n * const state = getDeployCommandState({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: 'SSH connection interrupted', ext: { commandExecution: { reason: 'exit', localTermination: 'confirmed', remoteExecution: 'unknown' } } })\n * if (state?.remoteExecution === 'unknown') process.stderr.write('Remote execution is unknown\\n')\n * ```\n */\nexport function getDeployCommandState(error: HaiError): DeployCommandState | undefined {\n const parsed = CommandStateSchema.safeParse(error.ext?.commandExecution)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * 读取错误中的恢复清单;仅返回明确允许展示的字段。\n * @param error - 上层捕获的部署 HaiError;不直接展示其 cause。\n * @returns 安全恢复清单;结构不满足约定时为 undefined。\n * @example\n * ```ts\n * import { getDeployRecovery, HaiDeployError } from '@h-ai/deploy'\n * const recovery = getDeployRecovery({ ...HaiDeployError.PROVISION_FAILED, message: 'Provisioning failed', ext: { recovery: { projectName: 'shop', stage: 'provision', resources: [] } } })\n * if (recovery) {\n * const stage = recovery.stage\n * }\n * ```\n */\nexport function getDeployRecovery(error: HaiError): DeployRecoveryInfo | undefined {\n const parsed = RecoverySchema.safeParse(error.ext?.recovery)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * 在错误中保留可展示的恢复信息,避免异常 cause/命令/URL 泄漏凭证。\n * @param error - 上层捕获的部署 HaiError;不直接展示其 cause。\n * @param recovery - 允许展示的恢复阶段与资源清单。\n * @returns 仅含安全恢复字段的失败 HaiResult。\n * @example 模块内部上下文\n * ```ts\n * const { HaiDeployError } = await import('./deploy-types.js')\n * const failure = recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: 'Provisioning failed' }, { projectName: 'shop', stage: 'provision', resources: [] })\n * if (!failure.success) {\n * const safeMessage = failure.error.message\n * }\n * ```\n */\nexport function recoveryFailure(error: HaiError, recovery: DeployRecoveryInfo): HaiResult<never> {\n return err({\n code: error.code,\n httpStatus: error.httpStatus,\n system: error.system,\n module: error.module,\n message: deployM('deploy_recoveryFailure', { params: { stage: recovery.stage } }),\n suggestion: deployM('deploy_recoverySuggestion'),\n ext: { recovery },\n })\n}\n","/** 应用、环境文件与中间件依赖扫描;不依赖 deploy.init(),不修改进程环境。 */\nimport type { HaiResult } from '@h-ai/core'\nimport type { DeployScanOptions, MiddlewareRequirement, ScanResult, ServiceType } from './deploy-types.js'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { parseAllDocuments } from 'yaml'\nimport { loadDeploymentConfig, loadDeploymentEnvironment } from './deploy-environment.js'\nimport { resolveProjectDirectory } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'scanner' })\n\n/** 安全缩窄 YAML/JSON 对象;数组与 null 不作为配置对象。 */\nfunction record(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\n/**\n * 从当前 workspace 的 lockfile 导入项遍历运行依赖,排除 dev 和 peer 边。\n * pnpm 12 的工具链和应用分别存于多个 YAML 文档,只选择含目标 importer 的应用文档。\n * 缺少 lockfile 或目标 importer 时要求先安装,不读取 package.json 或推测应用布局。\n */\nfunction runtimeDependencies(appDir: string): { runtime: Set<string>, build: Set<string>, root: string } {\n let root = appDir\n while (!existsSync(join(root, 'pnpm-lock.yaml'))) {\n const parent = dirname(root)\n if (parent === root)\n throw new Error('Missing pnpm lockfile; run pnpm install')\n root = parent\n }\n const importerKey = relative(root, appDir).replaceAll('\\\\', '/') || '.'\n const documents = parseAllDocuments(readFileSync(join(root, 'pnpm-lock.yaml'), 'utf8'))\n if (documents.some(document => document.errors.length))\n throw new Error('Invalid pnpm lockfile')\n const lock = documents.map(document => record(document.toJS())).reverse().find(document => importerKey in record(document.importers))\n if (!lock)\n throw new Error('Application is missing from pnpm lockfile; run pnpm install')\n const importers = record(lock.importers)\n const packages = record(lock.packages)\n const snapshots = record(lock.snapshots)\n const names = new Set<string>()\n const visited = new Set<string>()\n const visit = (id: string, node: Record<string, unknown>, importer?: string): void => {\n if (visited.has(id))\n return\n visited.add(id)\n const metadata = importer === undefined ? record(packages[id.split('(')[0]]) : {}\n const peers = record(metadata.peerDependencies)\n for (const [name, reference] of Object.entries({ ...record(node.dependencies), ...record(node.optionalDependencies) })) {\n if (name in peers)\n continue\n const version = typeof reference === 'string' ? reference : record(reference).version\n if (typeof version !== 'string')\n throw new Error('Invalid pnpm dependency reference')\n if (version.startsWith('link:')) {\n if (importer === undefined)\n throw new Error('Invalid workspace dependency')\n const target = relative(root, resolve(root, importer, version.slice(5))).replaceAll('\\\\', '/') || '.'\n const linked = record(importers[target])\n if (!Object.keys(linked).length)\n throw new Error('Missing linked workspace importer')\n names.add(name)\n visit(`workspace:${target}`, linked, target)\n continue\n }\n // npm alias 的引用已包含真实包名,不能再拼接别名。\n const key = version in snapshots || version in packages ? version : `${name}@${version}`\n names.add(key.match(/^(@[^/]+\\/[^@]+|[^@]+)@/)?.[1] ?? name)\n const snapshot = record(snapshots[key] ?? packages[key])\n if (!Object.keys(snapshot).length && !(key in snapshots) && !(key in packages))\n throw new Error('Missing pnpm dependency snapshot')\n visit(key, snapshot)\n }\n }\n visit(`workspace:${importerKey}`, record(importers[importerKey]), importerKey)\n return { runtime: names, build: new Set([...names, ...Object.keys(record(record(importers[importerKey]).devDependencies))]), root }\n}\n\n/**\n * 扫描依赖和实际环境下的后端,不把 memory/local/console 强制改为外部服务。\n * 沿目标 importer 的运行依赖识别模块;LDAP 等可选能力再按实际配置识别。\n * 以真实运行依赖图和显式配置识别模块;缺少或不一致锁文件不能静默降级为猜测。\n * @param inputDir - 待扫描的真实应用包目录。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 实际应用、依赖与中间件需求,或失败 HaiResult。\n * @example 模块内部上下文\n * ```ts\n * const result = await scanApp(process.cwd(), { environment: 'prod' })\n * if (!result.success) throw new Error(result.error.message)\n * const enabled = result.data.haiModules\n * ```\n */\nexport async function scanApp(inputDir: string, options?: DeployScanOptions): Promise<HaiResult<ScanResult>> {\n try {\n const appDir = resolve(inputDir)\n const graph = runtimeDependencies(appDir)\n // 服务目录只决定依赖和配置;资源属于工程,不能把 -serv 等工作区后缀带入部署名。\n const projectDir = resolveProjectDirectory(appDir)\n const packageFile = join(projectDir, 'package.json')\n const project = existsSync(packageFile) ? record(JSON.parse(readFileSync(packageFile, 'utf8'))) : {}\n if (typeof project.name !== 'string' || !project.name.trim())\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameRequired'))\n const appName = project.name.trim()\n if (!appName.replace(/^@[^/]+\\//, '').replace(/[^a-z0-9]/gi, ''))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameRequired'))\n const envDir = options?.envDir ? resolve(options.envDir) : existsSync(join(appDir, '.env')) ? appDir : graph.root\n const loaded = loadDeploymentEnvironment({ environment: options?.environment ?? 'prod', envDir, requireFile: options?.environment !== undefined })\n if (!loaded.success)\n return loaded\n const env = loaded.data.values\n const deps = graph.runtime\n const configs: Record<string, Record<string, unknown>> = {}\n for (const [name, owner] of Object.entries({ db: 'reldb', cache: 'cache', storage: 'storage', vecdb: 'vecdb', iam: 'iam', reach: 'reach' })) {\n configs[name] = {}\n if (!deps.has(`@h-ai/${owner}`))\n continue\n const configFile = ['yml', 'yaml'].map(ext => join(appDir, 'config', `_${name}.${ext}`)).find(existsSync)\n const config = configFile ? loadDeploymentConfig(name, configFile, env) : undefined\n if (config && !config.success)\n return config\n configs[name] = config?.data ?? {}\n }\n const middlewares: MiddlewareRequirement[] = []\n const add = (service: ServiceType, backend: string, configName = service as string, configPath: string[] = [], config = configs[configName] ?? {}, source = `_${configName}.yml`) => {\n middlewares.push({ service, backend, source, configName, configPath, envPrefix: ['HAI', configName, ...configPath].map(part => part.toUpperCase()).join('_'), config })\n }\n const iam = deps.has('@h-ai/iam')\n if (deps.has('@h-ai/reldb'))\n add('db', String(configs.db.type ?? 'sqlite'), 'db', [], configs.db, '@h-ai/reldb / _db.yml')\n if (deps.has('@h-ai/cache'))\n add('cache', String(configs.cache.type ?? 'memory'), 'cache', [], configs.cache, '@h-ai/cache / _cache.yml')\n if (deps.has('@h-ai/storage'))\n add('storage', String(configs.storage.type ?? 'local'))\n if (deps.has('@h-ai/vecdb'))\n add('vecdb', String(configs.vecdb.type ?? 'lancedb'))\n if (iam) {\n const ldap = record(configs.iam.ldap)\n add('ldap', record(configs.iam.login).ldap === true ? 'ldap' : 'disabled', 'iam', ['ldap'], ldap, '@h-ai/iam (LDAP)')\n }\n const providers = configs.reach.providers\n if (deps.has('@h-ai/reach') && Array.isArray(providers)) {\n for (const [index, item] of providers.entries()) {\n const provider = record(item)\n const type = String(provider.type ?? '')\n // Console/API 没有渠道字段,沿用生成应用的 sms Provider 名称识别短信。\n const service = type === 'aliyun-sms' || (['console', 'api'].includes(type) && provider.name === 'sms') ? 'sms' : ['smtp', 'api', 'console'].includes(type) ? 'email' : undefined\n if (service)\n add(service, type, 'reach', ['providers', String(index)], provider, '@h-ai/reach')\n }\n }\n if (deps.has('@h-ai/reach') && !middlewares.some(item => item.configName === 'reach'))\n add('email', 'console', 'reach', ['providers', '0'], { name: 'email', type: 'console' }, '@h-ai/reach')\n const isSvelteKit = graph.build.has('@sveltejs/kit')\n const scan: ScanResult = {\n appDir,\n envDir,\n middlewares,\n haiModules: [...deps].filter(name => name.startsWith('@h-ai/')).sort(),\n appName,\n isSvelteKit,\n adapterInstalled: graph.build.has('@sveltejs/adapter-vercel'),\n nodeAdapterInstalled: graph.build.has('@sveltejs/adapter-node'),\n requiredServices: [...new Set(middlewares.map(item => item.service))],\n serviceBackends: Object.fromEntries(middlewares.map(item => [item.service, item.backend])),\n }\n logger.info('Application scanned', { appName: scan.appName, haiModules: scan.haiModules, requiredServices: scan.requiredServices, serviceBackends: scan.serviceBackends })\n return ok(scan)\n }\n catch {\n // JSON/YAML 异常可能带有凭据行,不把原异常暴露到日志或用户错误。\n return err(HaiDeployError.SCAN_FAILED, deployM('deploy_scanFailed', { params: { error: 'Invalid or ambiguous application/configuration/lockfile; specify the application directory and run pnpm install' } }))\n }\n}\n","/**\n * 生成两个内部部署流程共用的 Compose 容器身份查询函数,不改变容器状态。\n * @returns POSIX Shell 函数 compose_container_ids(runtime, project, service, selector)。\n * @example 模块内部上下文\n * ```ts\n * const lookup = createComposeContainerLookupScript()\n * const apply = [lookup, 'compose_container_ids docker hai-demo-prod db -aq'].join('\\n')\n * // apply 供部署包内部执行,应用调用公开部署 API,不直接执行这段 Shell。\n * void apply\n * ```\n */\nexport function createComposeContainerLookupScript(): string {\n const labelFormat = ['com.docker.compose.project', 'com.docker.compose.service', 'io.podman.compose.project', 'io.podman.compose.service']\n .map(key => `{{index .Config.Labels \\`${key}\\`}}`)\n .join('|')\n return String.raw`compose_container_ids() (\n if [ \"$#\" -ne 4 ]; then printf 'Compose container lookup requires runtime, project, service and selector.\\n' >&2; exit 1; fi\n lookup_runtime=$1\n lookup_project=$2\n lookup_service=$3\n lookup_selector=$4\n case \"$lookup_runtime\" in docker|podman) ;; *) printf 'Invalid Compose lookup runtime.\\n' >&2; exit 1;; esac\n case \"$lookup_project\" in ''|*[!A-Za-z0-9_.-]*) printf 'Invalid Compose project identity.\\n' >&2; exit 1;; esac\n case \"$lookup_service\" in ''|*[!A-Za-z0-9_.-]*) printf 'Invalid Compose service identity.\\n' >&2; exit 1;; esac\n case \"$lookup_selector\" in -q|-aq) ;; *) printf 'Invalid Compose container selector.\\n' >&2; exit 1;; esac\n lookup_ids=''\n for lookup_namespace in com.docker.compose io.podman.compose; do\n lookup_found=$(\"$lookup_runtime\" ps \"$lookup_selector\" --filter \"label=$lookup_namespace.project=$lookup_project\" --filter \"label=$lookup_namespace.service=$lookup_service\") || { printf 'Cannot query Compose containers.\\n' >&2; exit 1; }\n printf '%s\\n' \"$lookup_found\" | LC_ALL=C awk 'NF {if(NF!=1 || $0!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/) exit 1}' || { printf 'Invalid Compose container identifiers.\\n' >&2; exit 1; }\n lookup_ids=$(printf '%s\\n%s\\n' \"$lookup_ids\" \"$lookup_found\" | LC_ALL=C awk 'NF && !seen[$0]++ {print}') || exit 1\n done\n for lookup_id in $lookup_ids; do\n lookup_labels=$(\"$lookup_runtime\" inspect --format '${labelFormat}' \"$lookup_id\") || { printf 'Cannot inspect Compose container labels.\\n' >&2; exit 1; }\n printf '%s\\n' \"$lookup_labels\" | LC_ALL=C awk -F'|' -v project=\"$lookup_project\" -v service=\"$lookup_service\" '\n NR!=1 || NF!=4 {exit 1}\n {\n docker=($1!=\"\" && $1!=\"<no value>\") || ($2!=\"\" && $2!=\"<no value>\")\n podman=($3!=\"\" && $3!=\"<no value>\") || ($4!=\"\" && $4!=\"<no value>\")\n if((!docker && !podman) || (docker && ($1!=project || $2!=service)) || (podman && ($3!=project || $4!=service))) exit 1\n }\n END {if(NR!=1) exit 1}\n ' || { printf 'Container labels do not confirm the requested Compose project and service.\\n' >&2; exit 1; }\n done\n if [ -n \"$lookup_ids\" ]; then printf '%s\\n' \"$lookup_ids\"; fi\n)\n`\n}\n","/** 自建中间件凭据在服务器定稿;打包机仅提供首次部署候选值。 */\nimport { parseEnv } from 'node:util'\nimport { deployM } from '../deploy-i18n.js'\n\nconst groups = [\n { name: 'DB_PASSWORD', keys: ['POSTGRES_PASSWORD', 'MYSQL_PASSWORD', 'MYSQL_ROOT_PASSWORD'], services: ['db', 'vecdb'] },\n { name: 'STORAGE_PASSWORD', keys: ['RUSTFS_SECRET_KEY', 'MINIO_ROOT_PASSWORD'], services: ['storage'] },\n { name: 'LDAP_PASSWORD', keys: ['LDAP_ADMIN_PASSWORD'], services: ['ldap'] },\n]\nconst appPrefixes: Record<string, string> = { db: 'HAI_DB', vecdb: 'HAI_VECDB', storage: 'HAI_STORAGE', ldap: 'HAI_IAM_LDAP' }\n\n/**\n * 按实际 Compose 声明解析命名卷,供凭据与后端身份清单共用。\n * @param projectName - 含环境的部署身份,不含 hai- 前缀。\n * @param mounts - 服务的 Compose volumes 字段。\n * @param declarations - Compose 顶层命名卷声明。\n * @returns 去重后的容器引擎实际卷名;忽略 bind mount。\n * @throws Error - 实际卷名不能安全写入部署清单。\n * @example 模块内部上下文\n * ```ts\n * const volumes = resolveComposeNamedVolumes('shop-prod', ['data:/data'], { data: null })\n * ```\n */\nexport function resolveComposeNamedVolumes(projectName: string, mounts: unknown, declarations: Record<string, unknown> = {}): string[] {\n if (!Array.isArray(mounts))\n return []\n const volumes = new Set<string>()\n for (const mount of mounts) {\n if (typeof mount !== 'string')\n continue\n const source = mount.split(':')[0]!\n if (!Object.hasOwn(declarations, source))\n continue\n const declaration = declarations[source]\n const details = declaration && typeof declaration === 'object' ? declaration : {}\n const volume = 'name' in details && typeof details.name === 'string'\n ? details.name\n : 'external' in details && details.external === true ? source : `hai-${projectName}_${source}`\n if (!/^\\w[\\w.-]*$/.test(volume))\n throw new Error(deployM('deploy_managedSecretsInvalid'))\n volumes.add(volume)\n }\n return [...volumes]\n}\n\n/**\n * 生成候选和卷身份清单;服务器以自己保存的状态覆盖候选,不把本机缓存当作长期凭据。\n * @param projectName - 含环境的部署身份,与 Compose project 参数一致。\n * @param nativeEnvironment - 仅供中间件使用的 dotenv。\n * @param compose - 当前生成的实际服务与命名卷。\n * @param compose.services - 实际启用的 Compose 服务。\n * @param compose.volumes - Compose 命名卷声明。\n * @returns 随不可变部署包传输的私有候选、卷清单和服务器执行脚本。\n * @throws Error - 候选不符合自动生成值格式,或同组凭据互相冲突。\n * @example 模块内部上下文\n * ```ts\n * const assets = createManagedSecretAssets('shop-test', '', { services: {} })\n * const script = assets['resolve-managed-secrets.sh']\n * ```\n */\nexport function createManagedSecretAssets(projectName: string, nativeEnvironment: string, compose: {\n services: Record<string, Record<string, unknown>>\n volumes?: Record<string, unknown>\n}): Record<string, string> {\n const native = parseEnv(nativeEnvironment)\n const candidates: string[] = []\n const bindings = new Set<string>()\n const volumes = new Set<string>()\n for (const group of groups) {\n const values = [...new Set(group.keys.flatMap(key => native[key] === undefined ? [] : [native[key]!]))]\n if (!values.length)\n continue\n if (values.length !== 1 || !/^[\\w-]{32}$/.test(values[0]!))\n throw new Error(deployM('deploy_managedSecretsInvalid'))\n candidates.push(`${group.name}=${values[0]}`)\n for (const key of group.keys.filter(key => native[key] !== undefined))\n bindings.add(`${group.name} ${key} exact`)\n for (const name of group.services) {\n const service = compose.services[name]\n if (!service?.env_file)\n continue\n bindings.add(`${group.name} ${appPrefixes[name]} prefix`)\n for (const volume of resolveComposeNamedVolumes(projectName, service.volumes, compose.volumes))\n volumes.add(`${group.name} ${volume}`)\n }\n }\n return {\n 'managed-project': `hai-${projectName}\\n`,\n 'managed-candidates.env': candidates.length ? `${candidates.join('\\n')}\\n` : '',\n 'managed-bindings': bindings.size ? `${[...bindings].join('\\n')}\\n` : '',\n 'managed-volumes': volumes.size ? `${[...volumes].join('\\n')}\\n` : '',\n 'resolve-managed-secrets.sh': createManagedSecretScript(),\n }\n}\n\n/**\n * 复用现有服务器凭据格式校验,不解码或输出任何凭据值。\n * @returns 定义 valid_values 的纯 Shell 片段,兼容首次候选与受控导入 v2。\n * @example 模块内部上下文\n * ```ts\n * const validation = createManagedSecretValidationScript()\n * const script = [validation, 'valid_values \"$credential_file\"'].join('\\n')\n * // 仅在部署包内校验可信路径,不将凭据内容写入日志或返回给浏览器。\n * void script\n * ```\n */\nexport function createManagedSecretValidationScript(): string {\n return String.raw`valid_values() {\n version=$(awk -F= '$1==\"FORMAT_VERSION\" {print $2}' \"$1\")\n if [ \"$version\" = 2 ]; then\n LC_ALL=C awk -F= '\n NF {\n if(NF!=2 || seen[$1]++) exit 1\n if($1==\"FORMAT_VERSION\") {if($2!=\"2\") exit 1; next}\n if($1==\"PROJECT\") {if($2!~/^[A-Za-z0-9][A-Za-z0-9_.-]*$/) exit 1; project=1; next}\n if($1~/^VOLUME_[0-9]+$/) {if($2!~/^(DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD):[A-Za-z0-9][A-Za-z0-9_.-]*$/) exit 1; next}\n if($1!~/^(DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD)$/ || $2!~/^[0-9a-f]+$/ || length($2)%2 || length($2)>8192) exit 1\n for(i=1;i<=length($2);i+=2) {b=substr($2,i,2); if(b~/^[01]/ || b==\"7f\") exit 1}\n }\n END {if(!project) exit 1}\n ' \"$1\"\n return\n fi\n LC_ALL=C awk -F= '\n NF {if(NF!=2 || $1!~/^(DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD)$/ || $2!~/^[A-Za-z0-9_-]+$/ || length($2)!=32 || seen[$1]++) exit 1}\n ' \"$1\"\n}\n`\n}\n\n/** 由 apply.sh 持有项目部署锁时调用,不输出密码值。 */\nfunction createManagedSecretScript(): string {\n return String.raw`#!/bin/sh\n# 由 apply.sh 在项目部署锁内调用;长期凭据只保存在服务器,不依赖打包机。\nset -eu\numask 077\nroot=$1\nrelease=$2\nruntime=$3\nstate=\"$root/managed-secrets.env\"\ncandidate_file=\"$release/managed-candidates.env\"\ntest -s \"$candidate_file\" || exit 0\nfail() { printf '%s\\n' \"$*\" >&2; exit 1; }\n@@MANAGED_VALUES_VALIDATOR@@\nvalue_of() { awk -F= -v key=\"$2\" '$1==key {print $2}' \"$1\"; }\ntest ! -L \"$state\" || fail \"Invalid managed middleware credential state: $state\"\nvalid_values \"$candidate_file\" || fail 'Invalid managed middleware credential candidates; rebuild the deployment bundle.'\nnext=\"$release/managed-secrets.next\"\nif [ -f \"$state\" ]; then\n test -s \"$state\" && valid_values \"$state\" || fail \"Invalid managed middleware credential state: $state. Restore its protected backup.\"\n cp \"$state\" \"$next\"\nelse\n : > \"$next\"\nfi\nformat=$(value_of \"$next\" FORMAT_VERSION)\nif [ \"$format\" = 2 ]; then\n test \"$(value_of \"$next\" PROJECT)\" = \"$(cat \"$release/managed-project\")\" || fail 'Managed middleware credential project mismatch.'\n known=$(\"$runtime\" volume ls -q) || fail 'Cannot check persistent volumes; managed middleware credentials were not changed.'\n while IFS=' ' read -r volume_group volume; do\n test -n \"$volume\" || continue\n binding=\"$volume_group:$volume\"\n if ! awk -F= -v binding=\"$binding\" '$1~/^VOLUME_[0-9]+$/ && $2==binding {found=1} END {exit !found}' \"$next\"; then\n if printf '%s\\n' \"$known\" | grep -Fxq \"$volume\"; then\n fail 'Existing persistent volume is not bound to the imported credential state. Import its verified identity first.'\n fi\n index=$(awk -F= '$1~/^VOLUME_[0-9]+$/ {n=substr($1,8)+0; if(n>max)max=n} END {print max+1}' \"$next\")\n printf 'VOLUME_%s=%s\\n' \"$index\" \"$binding\" >> \"$next\"\n fi\n done < \"$release/managed-volumes\"\nfi\nvolumes_checked=false\nknown_volumes=''\nwhile IFS='=' read -r name candidate; do\n test -n \"$name\" || continue\n value=$(value_of \"$next\" \"$name\")\n if [ -z \"$value\" ]; then\n if [ \"$volumes_checked\" = false ]; then\n known_volumes=$(\"$runtime\" volume ls -q) || fail 'Cannot check persistent volumes; managed middleware credentials were not changed.'\n volumes_checked=true\n fi\n while IFS=' ' read -r volume_group volume; do\n test \"$volume_group\" = \"$name\" || continue\n if printf '%s\\n' \"$known_volumes\" | grep -Fxq \"$volume\"; then\n fail \"Missing $name in $state for existing persistent volume $volume. Restore the server credential state before retrying.\"\n fi\n done < \"$release/managed-volumes\"\n value=$candidate\n if [ \"$format\" = 2 ]; then value=$(printf '%s' \"$candidate\" | od -An -tx1 | tr -d ' \\n'); fi\n printf '%s=%s\\n' \"$name\" \"$value\" >> \"$next\"\n fi\ndone < \"$candidate_file\"\nwhile IFS='=' read -r name candidate; do\n test -n \"$name\" || continue\n value=$(value_of \"$next\" \"$name\")\n for file in .env.runtime middleware.env middleware-runtime.env; do\n HAI_DEPLOY_SECRET_CANDIDATE=\"$candidate\" HAI_DEPLOY_SECRET_VALUE=\"$value\" LC_ALL=C awk -v group=\"$name\" -v format=\"$format\" '\n FILENAME==ARGV[1] {if($1==group) {keys[$2]=$3}; next}\n function replace_literal(line, needle, value, result, at) {\n result=\"\"\n while((at=index(line,needle))>0) {result=result substr(line,1,at-1) value; line=substr(line,at+length(needle))}\n return result line\n }\n function decode_hex(hex, result, i, high, low) {\n for(i=1;i<=length(hex);i+=2) {high=index(\"0123456789abcdef\",substr(hex,i,1))-1; low=index(\"0123456789abcdef\",substr(hex,i+1,1))-1; result=result sprintf(\"%c\",high*16+low)}\n return result\n }\n function json_escape(value, apostrophe, result, i, ch) {\n for(i=1;i<=length(value);i++) {\n ch=substr(value,i,1)\n if(ch==\"\\\\\") result=result \"\\\\\\\\\"\n else if(ch==\"\\\"\") result=result \"\\\\\\\"\"\n else if(ch==sprintf(\"%c\",39) && apostrophe) result=result \"\\\\u0027\"\n else result=result ch\n }\n return result\n }\n function uri_escape(value, result, i, ch, j, ordinal) {\n for(i=1;i<=length(value);i++) {\n ch=substr(value,i,1)\n if(ch~/[A-Za-z0-9_.~-]/) result=result ch\n else {ordinal=0; for(j=1;j<=255;j++) if(sprintf(\"%c\",j)==ch) {ordinal=j; break}; result=result sprintf(\"%%%02X\",ordinal)}\n }\n return result\n }\n {\n equal=index($0,\"=\"); key=substr($0,1,equal-1); scoped=0\n for(prefix in keys) if(key==prefix || (keys[prefix]==\"prefix\" && index(key,prefix \"_\")==1)) scoped=1\n if(scoped && format==2 && index($0,ENVIRON[\"HAI_DEPLOY_SECRET_CANDIDATE\"])>0) {\n candidate=ENVIRON[\"HAI_DEPLOY_SECRET_CANDIDATE\"]; value=decode_hex(ENVIRON[\"HAI_DEPLOY_SECRET_VALUE\"])\n literal=substr($0,equal+1); quote=sprintf(\"%c\",39)\n json=substr(literal,1,1)==quote && (substr(literal,2,1)==\"{\" || substr(literal,2,1)==\"[\")\n if(json) literal=substr(literal,2,length(literal)-2)\n literal=replace_literal(literal,\":\" candidate \"@\",\":\" uri_escape(value) \"@\")\n if(json) {literal=replace_literal(literal,candidate,json_escape(value,1)); print key \"=\" quote literal quote}\n else {\n if(substr(literal,1,1)==quote || substr(literal,1,1)==\"\\\"\") literal=substr(literal,2,length(literal)-2)\n literal=replace_literal(literal,candidate,value)\n literal=json_escape(literal,0); literal=replace_literal(literal,\"$\",\"$$\")\n print key \"=\\\"\" literal \"\\\"\"\n }\n }\n else if(scoped) print replace_literal($0,ENVIRON[\"HAI_DEPLOY_SECRET_CANDIDATE\"],ENVIRON[\"HAI_DEPLOY_SECRET_VALUE\"])\n else print\n }\n ' \"$release/managed-bindings\" \"$release/$file\" > \"$release/$file.next\"\n mv \"$release/$file.next\" \"$release/$file\"\n done\ndone < \"$candidate_file\"\nchmod 600 \"$next\"\nmv \"$next\" \"$state\"\nprintf '[INFO] Managed middleware credential source: %s (server state; values hidden).\\n' \"$state\"\n`.replace('@@MANAGED_VALUES_VALIDATOR@@', createManagedSecretValidationScript())\n}\n","/** 命名卷的后端身份独立于 current 拓扑保存,禁止把旧数据目录交给不兼容引擎。 */\nimport { deployM } from '../deploy-i18n.js'\nimport { createComposeContainerLookupScript } from './deploy-compose-identity.js'\nimport { createManagedSecretValidationScript, resolveComposeNamedVolumes } from './deploy-managed-secrets.js'\n\nconst backendFamilies: Record<string, readonly string[]> = {\n db: ['postgresql', 'mysql'],\n storage: ['rustfs', 'minio'],\n vecdb: ['qdrant', 'pgvector', 'chroma'],\n}\n\n/**\n * 为不可变部署包生成实际卷绑定和服务器校验脚本,仅供模块内部打包流程调用。\n * @param projectName - 已归一化、含环境的部署身份。\n * @param compose - 当前实际 Compose 服务与命名卷声明。\n * @param compose.services - 实际服务定义。\n * @param compose.volumes - 命名卷定义。\n * @param selected - 本包更新的服务;未选服务由成功基线补齐。\n * @returns 三列 state-backends 与固定本地引擎的身份校验脚本。\n * @throws Error - 有状态服务的引擎或实际卷绑定不符合生成契约。\n * @example 模块内部上下文\n * ```ts\n * const assets = createBackendStateAssets('shop-prod', { services: { db: { image: 'postgres:16', volumes: ['data:/data'] } }, volumes: { data: null } }, ['db'])\n * ```\n */\nexport function createBackendStateAssets(projectName: string, compose: {\n services: Record<string, Record<string, unknown>>\n volumes?: Record<string, unknown>\n}, selected: readonly string[]): Record<string, string> {\n if (!/^[\\w.-]+$/.test(projectName))\n throw new Error(deployM('deploy_artifactInvalid'))\n const tuples: string[] = []\n const volumes = new Set<string>()\n for (const serviceName of selected) {\n const families = backendFamilies[serviceName]\n if (!families)\n continue\n const service = compose.services[serviceName]\n const image = service?.image\n if (typeof image !== 'string')\n throw new Error(deployM('deploy_artifactInvalid'))\n const imageFamily = image.slice(image.lastIndexOf('/') + 1).split(':')[0]!\n const family = imageFamily === 'postgres' ? 'postgresql' : imageFamily\n const namedVolumes = resolveComposeNamedVolumes(projectName, service.volumes, compose.volumes)\n if (!families.includes(family) || namedVolumes.length !== 1 || volumes.has(namedVolumes[0]!))\n throw new Error(deployM('deploy_artifactInvalid'))\n const volume = namedVolumes[0]!\n volumes.add(volume)\n tuples.push(`${serviceName} ${family} ${volume}`)\n }\n return {\n 'state-backends': tuples.length ? `${tuples.join('\\n')}\\n` : '',\n 'resolve-backend-state.sh': createBackendStateScript()\n .replace('@@PROJECT@@', projectName)\n .replace('@@MANAGED_VALUES_VALIDATOR@@', createManagedSecretValidationScript())\n .replace('@@COMPOSE_CONTAINER_LOOKUP@@', createComposeContainerLookupScript()),\n }\n}\n\n/** 只在 apply.sh 持有项目部署锁时执行,不执行配置文件中的代码,不输出凭据。 */\nfunction createBackendStateScript(): string {\n return String.raw`#!/bin/sh\nset -eu\numask 077\nfail() { printf '%s\\n' \"$*\" >&2; exit 1; }\ntest \"$#\" -eq 5 || fail 'Backend state requires root, release, runtime, previous ID and mode.'\nroot=$1\nrelease=$2\nruntime=$3\nprevious=$4\nmode=$5\nproject='hai-@@PROJECT@@'\nstate=\"$root/persistent-backends\"\nsnapshot=\"$release/previous-state-backends\"\ncase \"$mode\" in check|commit|recover) ;; *) fail 'Invalid backend state mode.';; esac\ncase \"$runtime\" in docker|podman) ;; *) fail 'Backend state requires a resolved container runtime.';; esac\ncase \"$previous\" in .|..|*[!A-Za-z0-9_.-]*) fail 'Invalid previous deployment identity.';; esac\ntest -d \"$root\" && test ! -L \"$root\" && test -d \"$release\" && test ! -L \"$release\" || fail 'Invalid backend state directory.'\nregular() { test -f \"$1\" && test ! -L \"$1\" || fail \"Backend state must be a regular file: $1\"; }\nabsent_or_regular() { if [ -e \"$1\" ] || [ -L \"$1\" ]; then regular \"$1\"; fi; }\nvalid_tuples() {\n LC_ALL=C awk -v legacy=\"$2\" '\n NF {\n if((NF!=3 && !(legacy==1 && NF==2)) || roles[$1]++) exit 1\n if(!(($1==\"db\" && $2~/^(postgresql|mysql)$/) || ($1==\"storage\" && $2~/^(rustfs|minio)$/) || ($1==\"vecdb\" && $2~/^(qdrant|pgvector|chroma)$/))) exit 1\n if(NF==3 && ($3!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ || volumes[$3]++)) exit 1\n }\n ' \"$1\"\n}\nvalid_state() {\n LC_ALL=C awk -v snapshot=\"$2\" '\n NR==1 {if($0!=\"FORMAT_VERSION 1\") exit 1; next}\n NR==2 {if(NF!=2 || $1!=\"RUNTIME\" || $2!~/^(docker|podman)$/) exit 1; next}\n NR==3 {if(NF!=2 || $1!=\"UID\" || $2!~/^[0-9]+$/) exit 1; next}\n NR==4 {if(NF!=2 || $1!=\"IDENTITY\" || $2!~/^[0-9a-f]+$/ || length($2)!=64) exit 1; next}\n NR==5 {if(NF!=2 || $1!=\"PROJECT\" || $2!~/^hai-[A-Za-z0-9_.-]+$/) exit 1; next}\n NR==6 && snapshot==1 {if(NF!=2 || $1!=\"PREVIOUS\" || $2!~/^[A-Za-z0-9_.-]+$/) exit 1; next}\n {\n if(NF!=3 || volumes[$3]++ || (snapshot==1 && roles[$1]++)) exit 1\n if(!(($1==\"db\" && $2~/^(postgresql|mysql)$/) || ($1==\"storage\" && $2~/^(rustfs|minio)$/) || ($1==\"vecdb\" && $2~/^(qdrant|pgvector|chroma)$/))) exit 1\n if($3!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/) exit 1\n }\n END {if(NR<5+snapshot) exit 1}\n ' \"$1\"\n}\n# 本机制只支持固定用户的本地默认引擎。连接名称或路径不证明数据格式,更换存储需独立迁移。\nenv | LC_ALL=C awk -F= '$1~/^(DOCKER_HOST|DOCKER_CONTEXT|CONTAINER_HOST|CONTAINER_CONNECTION|CONTAINERS_STORAGE_CONF|CONTAINERS_CONF|STORAGE_DRIVER|STORAGE_OPTS)$/ && length(substr($0,index($0,\"=\")+1)) {exit 1}' || fail 'Remote or overridden container storage is unsupported for persistent backend state. Use a fixed local default engine.'\nowner=$(id -u) || fail 'Cannot identify the deployment user.'\ncase \"$owner\" in ''|*[!0-9]*) fail 'Invalid deployment user identity.';; esac\nif [ \"$runtime\" = docker ]; then\n context=$(docker context show) || fail 'Cannot check the Docker context.'\n test \"$context\" = default || fail 'Persistent backend state requires the default local Docker context.'\n engine=$(docker info --format '{{.ID}}|{{.DockerRootDir}}|{{.Driver}}') || fail 'Cannot identify the local Docker daemon.'\nelse\n remote=$(podman info --format '{{.Host.ServiceIsRemote}}') || fail 'Cannot check whether Podman is local.'\n test \"$remote\" = false || fail 'Persistent backend state requires local Podman; remote connections are unsupported.'\n engine=$(podman info --format '{{.Host.Hostname}}|{{.Store.GraphRoot}}|{{.Store.GraphDriverName}}') || fail 'Cannot identify the local Podman store.'\nfi\nprintf '%s\\n' \"$engine\" | LC_ALL=C awk -F'|' 'NR!=1 || NF!=3 || $1==\"\" || $1==\"<no value>\" || $2!~/^\\// || $3==\"\" || $3==\"<no value>\" {exit 1}' || fail 'Incomplete container store identity; no services were started.'\nidentity=$(printf '%s\\n%s\\n%s\\n' \"$runtime\" \"$owner\" \"$engine\" | sha256sum | awk '{print $1}')\nprintf '%s\\n' \"$identity\" | LC_ALL=C awk 'NR!=1 || $0!~/^[0-9a-f]+$/ || length($0)!=64 {exit 1}' || fail 'Cannot calculate the container store identity.'\nheader=$(printf 'FORMAT_VERSION 1\\nRUNTIME %s\\nUID %s\\nIDENTITY %s\\nPROJECT %s' \"$runtime\" \"$owner\" \"$identity\" \"$project\")\nsame_identity() {\n test \"$(sed -n '1,5p' \"$1\")\" = \"$header\" || fail 'Deployment project, container runtime, user or daemon/store identity changed. Use a separate deployment identity and migrate or restore data explicitly.'\n}\nabsent_or_regular \"$state\"\nledger=''\nif [ -f \"$state\" ]; then\n valid_state \"$state\" 0 || fail 'Invalid persistent backend ledger. Restore its protected backup.'\n same_identity \"$state\"\n ledger=$(sed -n '6,$p' \"$state\")\nfi\nknown=$(\"$runtime\" volume ls -q) || fail 'Cannot list persistent volumes; no backend state was changed.'\nprintf '%s\\n' \"$known\" | LC_ALL=C awk 'NF {if(NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ || seen[$1]++) exit 1}' || fail 'Invalid persistent volume listing.'\nexists_volume() { printf '%s\\n' \"$known\" | grep -Fxq \"$1\"; }\nledger_tuple() { printf '%s\\n' \"$ledger\" | awk -v volume=\"$1\" '$3==volume {print}'; }\n@@MANAGED_VALUES_VALIDATOR@@\n@@COMPOSE_CONTAINER_LOOKUP@@\n# 仅供旧状态补证:卷挂载和镜像均取自同项目、同角色的唯一实际容器。\ncontainer_binding() {\n binding_service=$1\n binding_family=$2\n binding_expected=$3\n binding_running=$4\n binding_flags=-aq\n if [ \"$binding_running\" = true ]; then binding_flags=-q; fi\n binding_containers=$(compose_container_ids \"$runtime\" \"$project\" \"$binding_service\" \"$binding_flags\") || fail 'Cannot inspect successful deployment containers.'\n printf '%s\\n' \"$binding_containers\" | LC_ALL=C awk 'NR!=1 || NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ {exit 1} END {if(NR!=1) exit 1}' || fail \"Cannot prove the previous volume binding for $binding_service. Restore verified backend state.\"\n if [ \"$binding_running\" = true ]; then\n binding_status=$(\"$runtime\" inspect --format '{{.State.Running}}' \"$binding_containers\") || fail 'Cannot verify the imported service is running.'\n test \"$binding_status\" = true || fail \"Imported backend requires its verified original container to be running: $binding_service.\"\n fi\n binding_mounted=$(\"$runtime\" inspect --format '{{range .Mounts}}{{if eq .Type \"volume\"}}{{println .Name}}{{end}}{{end}}' \"$binding_containers\") || fail 'Cannot inspect previous named volume mounts.'\n printf '%s\\n' \"$binding_mounted\" | LC_ALL=C awk 'NR!=1 || NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ {exit 1} END {if(NR!=1) exit 1}' || fail \"Ambiguous previous volume binding for $binding_service.\"\n binding_image=$(\"$runtime\" inspect --format '{{.Config.Image}}' \"$binding_containers\") || fail 'Cannot identify the previous container image.'\n binding_actual_family=$(printf '%s\\n' \"$binding_image\" | LC_ALL=C awk 'NR!=1 || NF!=1 {exit 1} {image=$0; sub(/^.*\\//,\"\",image); sub(/[:@].*$/,\"\",image); if(image==\"postgres\") image=\"postgresql\"; print image}') || fail 'Invalid previous container image identity.'\n test \"$binding_actual_family\" = \"$binding_family\" || fail \"Actual previous container image does not confirm its backend family: $binding_service.\"\n if [ -n \"$binding_expected\" ] && [ \"$binding_expected\" != \"$binding_mounted\" ]; then fail \"Actual previous volume differs from its backend manifest: $binding_service.\"; fi\n printf '%s\\n' \"$binding_mounted\"\n}\nconfirmed_import() {\n import_service=$1\n import_family=$2\n import_volume=$3\n import_state=\"$root/managed-secrets.env\"\n test -f \"$import_state\" && test ! -L \"$import_state\" || return 1\n valid_values \"$import_state\" || return 1\n test \"$(awk -F= '$1==\"FORMAT_VERSION\" {print $2}' \"$import_state\")\" = 2 || return 1\n test \"$(awk -F= '$1==\"PROJECT\" {print $2}' \"$import_state\")\" = \"$project\" || return 1\n case \"$import_service\" in db|vecdb) import_group=DB_PASSWORD;; storage) import_group=STORAGE_PASSWORD;; *) return 1;; esac\n awk -F= -v group=\"$import_group\" -v binding=\"$import_group:$import_volume\" '$1==group && $2!=\"\" {credential=1} $1~/^VOLUME_[0-9]+$/ && $2==binding {volume=1} END {exit !(credential && volume)}' \"$import_state\" || return 1\n # 密码不证明目录格式;受控导入还须与唯一运行原容器的实际卷及镜像家族共同吻合。\n import_actual=$(container_binding \"$import_service\" \"$import_family\" \"$import_volume\" true) || return 1\n test \"$import_actual\" = \"$import_volume\"\n}\nsnapshot_previous=$previous\nif [ -z \"$snapshot_previous\" ]; then snapshot_previous=-; fi\nif [ \"$mode\" = recover ]; then\n regular \"$snapshot\"\n valid_state \"$snapshot\" 1 || fail 'Invalid previous backend snapshot; automatic recovery is refused.'\n same_identity \"$snapshot\"\n test \"$(sed -n '6p' \"$snapshot\")\" = \"PREVIOUS $snapshot_previous\" || fail 'Previous backend snapshot does not match the recovery release.'\n while IFS=' ' read -r recover_service recover_family recover_volume; do\n test -n \"$recover_service\" || continue\n exists_volume \"$recover_volume\" || fail \"Previous persistent volume is missing: $recover_volume. Restore its backup before recovery.\"\n test \"$(ledger_tuple \"$recover_volume\")\" = \"$recover_service $recover_family $recover_volume\" || fail \"Previous persistent backend identity is unconfirmed: $recover_service. Automatic recovery is refused.\"\n done <<RECOVERY_TUPLES\n$(sed -n '7,$p' \"$snapshot\")\nRECOVERY_TUPLES\n exit 0\nfi\nregular \"$release/state-backends\"\nvalid_tuples \"$release/state-backends\" 0 || fail 'Invalid backend manifest; rebuild the deployment bundle.'\nactive=''\nif [ -n \"$previous\" ]; then\n baseline=\"$root/releases/$previous\"\n test -d \"$root/releases\" && test ! -L \"$root/releases\" && test -d \"$baseline\" && test ! -L \"$baseline\" || fail 'Invalid successful deployment directory.'\n regular \"$baseline/services\"\n regular \"$baseline/compose-files\"\n LC_ALL=C awk 'NF {if(NF!=1 || $1!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/ || seen[$1]++) exit 1}' \"$baseline/services\" || fail 'Invalid successful deployment services.'\n for active_service in db storage vecdb; do\n if ! grep -Fxq \"$active_service\" \"$baseline/services\"; then continue; fi\n active_family=''\n active_volume=''\n while IFS= read -r compose_file; do\n compose_directory=$(dirname -- \"$compose_file\")\n compose_id=$(basename -- \"$compose_directory\")\n case \"$compose_id\" in ''|.|..|*[!A-Za-z0-9_.-]*) fail 'Invalid successful Compose identity.';; esac\n test \"$compose_directory\" = \"$root/releases/$compose_id\" && test ! -L \"$compose_directory\" || fail 'Successful Compose file escapes the deployment directory.'\n regular \"$compose_file\"\n previous_manifest=\"$compose_directory/state-backends\"\n absent_or_regular \"$previous_manifest\"\n if [ -f \"$previous_manifest\" ]; then\n valid_tuples \"$previous_manifest\" 1 || fail 'Invalid successful backend manifest.'\n recorded=$(awk -v service=\"$active_service\" '$1==service {print}' \"$previous_manifest\")\n if [ -n \"$recorded\" ]; then\n active_family=$(printf '%s\\n' \"$recorded\" | awk '{print $2}')\n active_volume=$(printf '%s\\n' \"$recorded\" | awk '{print $3}')\n fi\n fi\n done < \"$baseline/compose-files\"\n if [ -z \"$active_family\" ]; then\n # 兼容旧包只读取已知字段,不 source dotenv;凭据本身不是后端身份的证据。\n case \"$active_service\" in\n db|vecdb)\n regular \"$baseline/middleware.env\"\n state_key=HAI_DB\n if [ \"$active_service\" = vecdb ]; then state_key=HAI_VECDB; fi\n active_family=$(awk -F= -v key=\"$state_key\" '$1==key {if($0~/\"type\"[[:space:]]*:[[:space:]]*\"postgresql\"/) print \"postgresql\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"mysql\"/) print \"mysql\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"qdrant\"/) print \"qdrant\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"pgvector\"/) print \"pgvector\"; else if($0~/\"type\"[[:space:]]*:[[:space:]]*\"chroma\"/) print \"chroma\"}' \"$baseline/middleware.env\")\n ;;\n storage)\n regular \"$baseline/middleware-runtime.env\"\n active_family=$(awk -F= '$1==\"RUSTFS_SECRET_KEY\" {print \"rustfs\"} $1==\"MINIO_ROOT_PASSWORD\" {print \"minio\"}' \"$baseline/middleware-runtime.env\")\n ;;\n esac\n fi\n # 旧两列清单或丢失账本只能以当前真实容器的命名卷挂载补证,不猜默认卷名。\n if [ -z \"$active_volume\" ] || [ -z \"$(ledger_tuple \"$active_volume\")\" ]; then\n active_volume=$(container_binding \"$active_service\" \"$active_family\" \"$active_volume\" false) || fail \"Cannot confirm the active persistent backend: $active_service.\"\n fi\n printf '%s %s %s\\n' \"$active_service\" \"$active_family\" \"$active_volume\" | LC_ALL=C awk 'NF!=3 || !(($1==\"db\" && $2~/^(postgresql|mysql)$/) || ($1==\"storage\" && $2~/^(rustfs|minio)$/) || ($1==\"vecdb\" && $2~/^(qdrant|pgvector|chroma)$/)) {exit 1}' || fail \"Unknown previous backend for $active_service; explicit migration is required.\"\n exists_volume \"$active_volume\" || fail \"Active persistent volume is missing: $active_volume. Restore its backup instead of creating an empty replacement.\"\n confirmed=$(ledger_tuple \"$active_volume\")\n test -z \"$confirmed\" || test \"$confirmed\" = \"$active_service $active_family $active_volume\" || fail \"Active persistent backend conflicts with the protected ledger: $active_service.\"\n active=$(printf '%s\\n%s %s %s\\n' \"$active\" \"$active_service\" \"$active_family\" \"$active_volume\" | sed '/^$/d')\n done\nfi\n# 各个旧 Compose 片段不能把同一实际卷重复绑定给不同有状态角色。\nprintf '%s\\n' \"$active\" | valid_tuples /dev/stdin 0 || fail 'Conflicting successful persistent volume bindings.'\n# 合并时只替换同一卷的无数据预认领,不能按本次拓扑裁剪历史绑定。\nmerged=$ledger\nmerge_tuple() {\n merged=$(printf '%s\\n' \"$merged\" | awk -v volume=\"$3\" 'NF && $3!=volume {print}')\n merged=$(printf '%s\\n%s %s %s\\n' \"$merged\" \"$1\" \"$2\" \"$3\" | sed '/^$/d')\n}\nwhile IFS=' ' read -r active_service active_family active_volume; do\n test -n \"$active_service\" || continue\n merge_tuple \"$active_service\" \"$active_family\" \"$active_volume\"\ndone <<ACTIVE_TUPLES\n$active\nACTIVE_TUPLES\nwhile IFS=' ' read -r candidate_service candidate_family candidate_volume; do\n test -n \"$candidate_service\" || continue\n prior_active=$(printf '%s\\n' \"$active\" | awk -v service=\"$candidate_service\" '$1==service {print}')\n tuple=\"$candidate_service $candidate_family $candidate_volume\"\n test -z \"$prior_active\" || test \"$prior_active\" = \"$tuple\" || fail \"Persistent backend $candidate_service changed or its active volume binding changed. Use a separate deployment identity and migrate or restore data explicitly.\"\n if exists_volume \"$candidate_volume\"; then\n confirmed=$(ledger_tuple \"$candidate_volume\")\n if [ -z \"$confirmed\" ]; then confirmed=$(printf '%s\\n' \"$active\" | awk -v volume=\"$candidate_volume\" '$3==volume {print}'); fi\n if [ -z \"$confirmed\" ] && confirmed_import \"$candidate_service\" \"$candidate_family\" \"$candidate_volume\"; then confirmed=$tuple; fi\n test \"$confirmed\" = \"$tuple\" || fail \"Existing persistent volume has an unknown or incompatible backend: $candidate_service. Restore verified backend state; in-place reuse is refused.\"\n else\n users=$(\"$runtime\" ps -aq --filter \"volume=$candidate_volume\") || fail 'Cannot check persistent volume users.'\n test -z \"$users\" || fail \"A container still references missing persistent volume $candidate_volume. Restore or migrate explicitly.\"\n fi\n merge_tuple \"$candidate_service\" \"$candidate_family\" \"$candidate_volume\"\ndone < \"$release/state-backends\"\nabsent_or_regular \"$snapshot\"\nif [ -e \"$snapshot.next\" ] || [ -L \"$snapshot.next\" ] || [ -e \"$state.next\" ] || [ -L \"$state.next\" ]; then fail 'Backend state staging file already exists; inspect the interrupted deployment before retrying.'; fi\nif [ \"$mode\" = check ]; then exit 0; fi\nsnapshot_content=$(printf '%s\\nPREVIOUS %s\\n' \"$header\" \"$snapshot_previous\"; if [ -n \"$active\" ]; then printf '%s\\n' \"$active\"; fi)\nstate_content=$(printf '%s\\n' \"$header\"; if [ -n \"$merged\" ]; then printf '%s\\n' \"$merged\"; fi)\n# 独占创建同目录临时文件;只有完整快照与账本均落盘后,主流程才可启动或恢复服务。\n(set -C; printf '%s\\n' \"$snapshot_content\" > \"$snapshot.next\") || fail 'Cannot stage the previous backend snapshot.'\nchmod 600 \"$snapshot.next\"\nmv -f -- \"$snapshot.next\" \"$snapshot\"\n(set -C; printf '%s\\n' \"$state_content\" > \"$state.next\") || fail 'Cannot stage the persistent backend ledger.'\nchmod 600 \"$state.next\"\nmv -f -- \"$state.next\" \"$state\"\n`\n}\n","/** Windows Job Object 桥接:静态代码内嵌在包中,参数只通过私有环境入口传递。 */\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\n\n// Native 结构与语义按 Windows SDK;创建时挂起,分配成功后才恢复,避免子进程逃离 Job。\n// https://learn.microsoft.com/windows/win32/procthread/job-objects\nconst nativeJob = String.raw`\nusing System;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\n\npublic static class HaiCommandJob {\n [StructLayout(LayoutKind.Sequential)] struct BasicLimits {\n public long ProcessTime, JobTime;\n public uint Flags;\n public UIntPtr MinimumWorkingSet, MaximumWorkingSet;\n public uint ActiveProcessLimit;\n public UIntPtr Affinity;\n public uint PriorityClass, SchedulingClass;\n }\n [StructLayout(LayoutKind.Sequential)] struct IoCounters {\n public ulong ReadOperations, WriteOperations, OtherOperations, ReadBytes, WriteBytes, OtherBytes;\n }\n [StructLayout(LayoutKind.Sequential)] struct ExtendedLimits {\n public BasicLimits Basic;\n public IoCounters Io;\n public UIntPtr ProcessMemory, JobMemory, PeakProcessMemory, PeakJobMemory;\n }\n [StructLayout(LayoutKind.Sequential)] struct Accounting {\n public long UserTime, KernelTime, PeriodUserTime, PeriodKernelTime;\n public uint Faults, Total, Active, Terminated;\n }\n [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct Startup {\n public uint Size;\n public string Reserved, Desktop, Title;\n public uint X, Y, Width, Height, XChars, YChars, Fill, Flags;\n public ushort Show, ReservedSize;\n public IntPtr ReservedData, Input, Output, Error;\n }\n [StructLayout(LayoutKind.Sequential)] struct ProcessInfo {\n public IntPtr Process, Thread;\n public uint ProcessId, ThreadId;\n }\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr CreateJobObject(IntPtr attributes, string name);\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr OpenJobObject(uint access, bool inherit, string name);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool SetInformationJobObject(IntPtr job, int kind, ref ExtendedLimits information, uint size);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool QueryInformationJobObject(IntPtr job, int kind, out Accounting information, uint size, IntPtr length);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool CreateProcess(string application, StringBuilder command, IntPtr processAttributes, IntPtr threadAttributes, bool inherit, uint flags, IntPtr environment, string directory, ref Startup startup, out ProcessInfo information);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern uint ResumeThread(IntPtr thread);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool TerminateProcess(IntPtr process, uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool TerminateJobObject(IntPtr job, uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool GetExitCodeProcess(IntPtr process, out uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool CloseHandle(IntPtr handle);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern IntPtr GetStdHandle(int kind);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool SetHandleInformation(IntPtr handle, uint mask, uint flags);\n\n static void Check(bool success) { if (!success) throw new Win32Exception(Marshal.GetLastWin32Error()); }\n static uint Active(IntPtr job) {\n Accounting information;\n Check(QueryInformationJobObject(job, 1, out information, (uint)Marshal.SizeOf(typeof(Accounting)), IntPtr.Zero));\n return information.Active;\n }\n // Windows argv 编码:引号前与结尾的反斜杠加倍,其余字符原样传递,不经过命令 shell。\n static string Quote(string value) {\n StringBuilder result = new StringBuilder(\"\\\"\");\n int slashes = 0;\n foreach (char current in value) {\n if (current == '\\\\') { slashes++; continue; }\n if (current == '\"') result.Append('\\\\', slashes * 2 + 1);\n else result.Append('\\\\', slashes);\n result.Append(current);\n slashes = 0;\n }\n result.Append('\\\\', slashes * 2).Append('\"');\n return result.ToString();\n }\n public static int Run(string name, string command, string[] arguments) {\n IntPtr job = CreateJobObject(IntPtr.Zero, name);\n if (job == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());\n ProcessInfo process = new ProcessInfo();\n bool assigned = false;\n try {\n ExtendedLimits limits = new ExtendedLimits();\n limits.Basic.Flags = 0x2000; // JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;不允许 breakaway。\n Check(SetInformationJobObject(job, 9, ref limits, (uint)Marshal.SizeOf(typeof(ExtendedLimits))));\n StringBuilder line = new StringBuilder(Quote(command));\n foreach (string argument in arguments) line.Append(' ').Append(Quote(argument));\n Startup startup = new Startup();\n startup.Size = (uint)Marshal.SizeOf(typeof(Startup));\n startup.Flags = 0x100;\n startup.Input = GetStdHandle(-10); startup.Output = GetStdHandle(-11); startup.Error = GetStdHandle(-12);\n Check(SetHandleInformation(startup.Input, 1, 1));\n Check(SetHandleInformation(startup.Output, 1, 1));\n Check(SetHandleInformation(startup.Error, 1, 1));\n Check(CreateProcess(null, line, IntPtr.Zero, IntPtr.Zero, true, 0x08000004, IntPtr.Zero, null, ref startup, out process));\n Check(AssignProcessToJobObject(job, process.Process));\n assigned = true;\n if (ResumeThread(process.Thread) == 0xFFFFFFFF) throw new Win32Exception(Marshal.GetLastWin32Error());\n if (WaitForSingleObject(process.Process, 0xFFFFFFFF) != 0) throw new Win32Exception(Marshal.GetLastWin32Error());\n uint code;\n Check(GetExitCodeProcess(process.Process, out code));\n while (Active(job) != 0) Thread.Sleep(20);\n return unchecked((int)code);\n }\n finally {\n if (process.Process != IntPtr.Zero) {\n // 分配失败时进程仍挂起,直接终止,不允许裸进程恢复;Job 在其他异常时同样清空。\n if (!assigned) TerminateProcess(process.Process, 125);\n else TerminateJobObject(job, 125);\n WaitForSingleObject(process.Process, 5000);\n }\n if (process.Thread != IntPtr.Zero) CloseHandle(process.Thread);\n if (process.Process != IntPtr.Zero) CloseHandle(process.Process);\n CloseHandle(job);\n }\n }\n public static bool Empty(string name) {\n IntPtr job = OpenJobObject(4, false, name); // JOB_OBJECT_QUERY\n if (job == IntPtr.Zero) {\n if (Marshal.GetLastWin32Error() == 2) return true;\n throw new Win32Exception(Marshal.GetLastWin32Error());\n }\n try { return Active(job) == 0; }\n finally { CloseHandle(job); }\n }\n}\n`\n\n/** 生成隐藏 PowerShell 的静态脚本;执行策略不影响内联命令,不加载用户 profile。 */\nfunction powershell(script: string): string[] {\n return ['-NoLogo', '-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(script, 'utf16le').toString('base64')]\n}\n\n/**\n * 创建命令 Job;参数不插入代码,启动失败直接拒绝,不能降级为无 Job 的裸进程。\n * 只生成 Job helper 的参数和私有环境载荷;调用者必须按约定启动 helper,不能直接恢复裸子进程。\n * @param command - 本地可执行文件名或绝对路径,不是 shell 命令串。\n * @param args - 逐项传入的参数数组,不再自行拼接 shell。\n * @returns Job 名、隐藏 PowerShell 参数与私有环境载荷。\n * @example 模块内部上下文\n * ```ts\n * const job = windowsCommand(process.execPath, ['--version'])\n * const probe = windowsJobProbe(job.name)\n * // job.args/env 供隐藏 powershell.exe 使用;不要记录其中的私有参数。\n * ```\n */\nexport function windowsCommand(command: string, args: string[]): { name: string, args: string[], env: Record<string, string> } {\n const name = `Local\\\\hai-deploy-${randomUUID()}`\n const key = `__HAI_DEPLOY_JOB_${randomUUID().replaceAll('-', '')}`\n const script = `$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $InformationPreference='SilentlyContinue'\ntry {\n Add-Type -TypeDefinition @'\n${nativeJob}\n'@\n $inputConfig = [Environment]::GetEnvironmentVariable('${key}') | ConvertFrom-Json\n [Environment]::SetEnvironmentVariable('${key}', $null)\n exit ([HaiCommandJob]::Run([string]$inputConfig.name, [string]$inputConfig.command, [string[]]$inputConfig.args))\n} catch { [Console]::Error.WriteLine('Windows command job failed'); exit 125 }`\n return { name, args: powershell(script), env: { [key]: JSON.stringify({ name, command, args }) } }\n}\n\n/**\n * 查询 Job 的真实成员数;不存在表示全部退出,任何检查故障均不能声称终止确认。\n * 名称必须来自 windowsCommand,不能把外部任意文本插入 PowerShell 探测脚本。\n * @param name - 由 windowsCommand 生成的内部 Job 名称。\n * @returns 探测静态脚本的 PowerShell 参数;探测返回码另行检查。\n * @example 模块内部上下文\n * ```ts\n * const job = windowsCommand(process.execPath, ['--version'])\n * const probeArgs = windowsJobProbe(job.name)\n * // 仅对本函数配套创建的 Job 名执行探测;0为空、1仍有成员、2为探测故障。\n * ```\n */\nexport function windowsJobProbe(name: string): string[] {\n return powershell(`$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $InformationPreference='SilentlyContinue'\ntry {\n Add-Type -TypeDefinition @'\n${nativeJob}\n'@\n if ([HaiCommandJob]::Empty('${name}')) { exit 0 } else { exit 1 }\n} catch { exit 2 }`)\n}\n","/** 管理命令的真实本地进程树;POSIX 使用独立进程组,Windows 使用不可 breakaway 的 Job。 */\nimport type { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio } from 'node:child_process'\nimport { spawn } from 'node:child_process'\nimport { readdir, readFile } from 'node:fs/promises'\nimport process from 'node:process'\nimport { setTimeout } from 'node:timers/promises'\nimport { windowsCommand, windowsJobProbe } from './deploy-command-windows.js'\n\n/** Linux 的孤儿 zombie 已退出,不能把未回收的 PID 当作仍执行的进程。 */\nasync function groupExited(pid: number): Promise<boolean> {\n try {\n process.kill(-pid, 0)\n }\n catch (error) {\n return error instanceof Error && 'code' in error && error.code === 'ESRCH'\n }\n if (process.platform !== 'linux')\n return false\n try {\n for (const entry of await readdir('/proc')) {\n if (!/^\\d+$/.test(entry))\n continue\n let stat: string\n try {\n stat = await readFile(`/proc/${entry}/stat`, 'utf8')\n }\n catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT')\n continue\n return false\n }\n // comm 可包含空格/括号,取最后一个右括号之后的固定字段。\n const fields = stat.slice(stat.lastIndexOf(')') + 2).split(' ')\n if (Number(fields[2]) === pid && fields[0] !== 'Z' && fields[0] !== 'X')\n return false\n }\n return true\n }\n catch {\n return false\n }\n}\n\n/** 辅助工具只返回退出码,既不捕获参数/输出,也不把原始错误传播到用户结果。 */\nasync function helper(command: string, args: string[], timeoutMs: number): Promise<boolean> {\n if (timeoutMs <= 0)\n return false\n return new Promise((resolve) => {\n const child = spawn(command, args, { windowsHide: true, shell: false, stdio: 'ignore' })\n let settled = false\n let timer: NodeJS.Timeout | undefined\n const finish = (success: boolean): void => {\n if (settled)\n return\n settled = true\n if (timer)\n clearTimeout(timer)\n resolve(success)\n }\n timer = globalThis.setTimeout(() => {\n child.kill('SIGKILL')\n child.unref()\n finish(false)\n }, timeoutMs)\n child.once('error', () => finish(false))\n child.once('close', code => finish(code === 0))\n })\n}\n\n/**\n * 只向命令执行器暴露必要控制,不把平台句柄或 Job 名称作为用户配置。\n * 控制句柄只管理本地进程树;调用 treeExited/terminate 后仍要按 boolean/状态判断,不推断远端副作用。\n * @example 模块内部上下文\n * ```ts\n * const controlled = spawnCommand(process.execPath, ['--version'], { cwd: process.cwd(), env: process.env })\n * const exited = await controlled.treeExited()\n * if (!exited) {\n * const termination = await controlled.terminate(10000)\n * if (termination === 'unknown') process.stderr.write('Termination unconfirmed\\n')\n * }\n * ```\n */\nexport interface CommandProcess {\n child: ChildProcessWithoutNullStreams\n treeExited: () => Promise<boolean>\n terminate: (timeoutMs: number) => Promise<'confirmed' | 'unknown'>\n}\n\n/**\n * 启动受管理进程;Windows helper/Job 失败时没有裸进程降级路径。\n * 由 runCommand 负责输出、异常与超时编排;此低层入口本身不提供 HaiResult 或脱敏。\n * @param command - 本地可执行文件名或绝对路径,不是 shell 命令串。\n * @param args - 逐项传入的参数数组,不再自行拼接 shell。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 受管理子进程及本地进程树检查/终止句柄。\n * @example 模块内部上下文\n * ```ts\n * const controlled = spawnCommand(process.execPath, ['--version'], { cwd: process.cwd(), env: process.env })\n * const exited = await controlled.treeExited()\n * if (!exited) {\n * const termination = await controlled.terminate(10000)\n * if (termination === 'unknown') process.stderr.write('Termination unconfirmed\\n')\n * }\n * ```\n */\nexport function spawnCommand(command: string, args: string[], options: Pick<SpawnOptionsWithoutStdio, 'cwd' | 'env'>): CommandProcess {\n const job = process.platform === 'win32' ? windowsCommand(command, args) : undefined\n const child = spawn(job ? 'powershell.exe' : command, job?.args ?? args, {\n ...options,\n env: job ? { ...options.env, ...job.env } : options.env,\n windowsHide: true,\n shell: false,\n detached: !job,\n })\n let exited = false\n child.once('exit', () => {\n exited = true\n })\n child.once('close', () => {\n exited = true\n })\n let termination: Promise<'confirmed' | 'unknown'> | undefined\n const treeExited = async (): Promise<boolean> => {\n if (!child.pid)\n return true\n if (job)\n return exited && helper('powershell.exe', windowsJobProbe(job.name), 5000)\n return groupExited(child.pid)\n }\n const terminate = (timeoutMs: number): Promise<'confirmed' | 'unknown'> => {\n termination ??= (async () => {\n const deadline = performance.now() + timeoutMs\n let windowsKillConfirmed = !job || exited\n if (child.pid) {\n if (job) {\n if (!exited) {\n // /T 也覆盖 Add-Type 的编译器;payload 的断链后代由 Job 的 close-kill 保证收回。\n windowsKillConfirmed = await helper('taskkill', ['/pid', String(child.pid), '/t', '/f'], Math.max(1, deadline - performance.now()))\n child.kill('SIGKILL')\n }\n }\n else {\n try {\n process.kill(-child.pid, 'SIGKILL')\n }\n catch {\n // 退出 race 或权限失败都必须由下方状态核验决定,不能把 kill 请求当确认。\n }\n }\n }\n while (performance.now() < deadline) {\n if (exited)\n break\n await setTimeout(20)\n }\n let verified = false\n if (exited && job) {\n // 原生命令已自然返回时,helper 已等待所有 Job 成员;被强杀则仍查询 Job 实际归零。\n verified = await helper('powershell.exe', windowsJobProbe(job.name), deadline - performance.now())\n verified &&= windowsKillConfirmed || child.exitCode !== null\n }\n else if (exited) {\n while (performance.now() < deadline) {\n if (await treeExited()) {\n verified = true\n break\n }\n await setTimeout(20)\n }\n }\n // exit 与管道 close 分开:消费者可仍等待回调,但不能据此误判进程仍运行。\n // 异常后丢弃未完成秘密尾部并关闭管道,不等待无法取消的已进入回调。\n child.stdin.destroy()\n child.stdout.destroy()\n child.stderr.destroy()\n if (!verified)\n child.unref()\n return verified ? 'confirmed' : 'unknown'\n })()\n return termination\n }\n return { child, treeExited, terminate }\n}\n","/** 已知秘密的跨块字面量脱敏;不会把秘密当成正则语法。 */\n\n/**\n * 单个逻辑文本流的脱敏器;UTF-8解码由调用方的StringDecoder完成。\n * @example 模块内部上下文\n * ```ts\n * const masker: SecretMasker = createSecretMasker(['example-token'])\n * const text = masker.write('example-') + masker.write('token public') + masker.end() // *** public\n * ```\n */\nexport interface SecretMasker {\n /** 接收已正确解码的下一块,仅释放不可能与后续块组成秘密的前缀。 */\n write: (text: string) => string\n /** 正常流结束时释放最后一块;重复调用为空,异常终止可丢弃未释放尾部。 */\n end: () => string\n}\n\n/**\n * 创建精确字面量流式脱敏器;最多保留最长秘密长度减一的尾部。\n * 每个逻辑流使用独立实例;write 可能延迟尾部,正常结束须 end,不能提前把缓冲原文输出。\n * @param secrets - 已知敏感值;忽略空值、去重,优先匹配同位置的较长值,总长度上限1Mi UTF-16单元\n * @returns 每次write/end的安全输出按顺序拼接得到完整脱敏文本\n * @throws 秘密总长度超限或底层表达式不能编译时抛错,调用方必须失败关闭\n * @example 模块内部上下文\n * ```ts\n * const masker = createSecretMasker(['example-token'])\n * const output = masker.write('example-') + masker.write('token public') + masker.end() // *** public\n * ```\n */\nexport function createSecretMasker(secrets: readonly string[] = []): SecretMasker {\n const values = [...new Set(secrets.filter(Boolean))].sort((a, b) => b.length - a.length)\n if (values.reduce((total, value) => total + value.length, 0) > 1048576)\n throw new RangeError('Secret redaction input is too large')\n const pattern = values.length ? new RegExp(values.map(value => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|'), 'g') : undefined\n const tailLength = Math.max(0, (values[0]?.length ?? 1) - 1)\n let pending = ''\n let ended = false\n\n /** 在原文边界上计算释放位置;不能从掩码中间切分后再释放其原文尾部。 */\n function drain(final: boolean): string {\n let end = final ? pending.length : Math.max(0, pending.length - tailLength)\n // 避免向分别编码/显示回调片段的消费者交付半个Unicode代理对。\n if (end > 0 && end < pending.length && /[\\uD800-\\uDBFF]/.test(pending[end - 1]!) && /[\\uDC00-\\uDFFF]/.test(pending[end]!))\n end--\n if (end === 0)\n return ''\n let cursor = 0\n let output = ''\n if (pattern) {\n pattern.lastIndex = 0\n let match = pattern.exec(pending)\n while (match && match.index < end) {\n output += `${pending.slice(cursor, match.index)}***`\n cursor = pattern.lastIndex\n // 跨释放边界的完整匹配整体消费,不能在后续write重新暴露其后半段。\n end = Math.max(end, cursor)\n match = pattern.exec(pending)\n }\n }\n output += pending.slice(cursor, end)\n pending = pending.slice(end)\n return output\n }\n\n return {\n write(text) {\n if (ended)\n throw new Error('Secret masker has ended')\n pending += text\n return drain(false)\n },\n end() {\n if (ended)\n return ''\n ended = true\n return drain(true)\n },\n }\n}\n","/**\n * @h-ai/deploy — 命令执行器。\n * command与args分离,不经过shell;流式回调、捕获结果和错误使用相同秘密脱敏边界。\n * @module deploy-command\n */\nimport type { HaiResult } from '@h-ai/core'\nimport type { DeployCommandState } from '../deploy-types.js'\nimport process from 'node:process'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { spawnCommand } from './deploy-command-process.js'\nimport { createSecretMasker } from './deploy-secret-masker.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'command' })\n\n/**\n * 命令执行选项;secrets必须列出可能输出的已知敏感值。\n * @example 模块内部上下文\n * ```ts\n * const options: CommandOptions = { cwd: process.cwd(), timeoutMs: 5000, terminationTimeoutMs: 10000, maxCaptureChars: 4096 }\n * const result = await runCommand(process.execPath, ['--version'], options)\n * if (!result.success) throw new Error(result.error.message)\n * ```\n */\nexport interface CommandOptions {\n /** 正确UTF-8解码且跨块脱敏的stdout片段;顺序完整,末尾可能延迟至close。 */\n onOutput?: (output: string) => void | Promise<void>\n /** 工作目录。 */\n cwd?: string\n /** 追加环境;不会自动将全部环境值视为秘密。 */\n env?: Record<string, string>\n /** 超时毫秒,须为 1..2147483647 的整数;超时不代表远程进程已终止。 */\n timeoutMs?: number\n /** 超时/异常后核验本地树退出的最长等待,默认 10 秒,最大 60 秒;未确认时返回 unknown。 */\n terminationTimeoutMs?: number\n /** 通过stdin传入的内容。 */\n input?: string\n /** 已知敏感字面量;总长度最多1Mi UTF-16单元,超限失败关闭。 */\n secrets?: string[]\n /** 每条捕获流保留的尾部字符上限,默认1Mi,最大16Mi;回调仍接收全部安全stdout。 */\n maxCaptureChars?: number\n}\n\n/**\n * 已脱敏的有界命令结果;解析结构化输出前必须拒绝截断结果。\n * 仅保存脱敏流的有界尾部;不把尾部捕获当作完整日志。\n * @example 模块内部上下文\n * ```ts\n * const result = await runCommand(process.execPath, ['--version'], { maxCaptureChars: 4096 })\n * if (!result.success) throw new Error(result.error.message)\n * const output: CommandResult = result.data\n * const truncated = output.stdoutTruncated\n * ```\n */\nexport interface CommandResult {\n /** 实际退出码。 */\n code: number\n /** 已脱敏stdout尾部。 */\n stdout: string\n /** 已脱敏stderr尾部。 */\n stderr: string\n /** stdout是否超过捕获上限。 */\n stdoutTruncated: boolean\n /** stderr是否超过捕获上限。 */\n stderrTruncated: boolean\n}\n\n/**\n * 对完整文本进行同样的精确字面量脱敏。\n * @param text - 完整文本\n * @param secrets - 已知秘密\n * @returns 脱敏文本\n * @example 模块内部上下文\n * ```ts\n * const text = maskSecrets('example-token public', ['example-token']) // *** public;合成字符串只用于演示。\n * ```\n */\nexport function maskSecrets(text: string, secrets: string[] = []): string {\n const masker = createSecretMasker(secrets)\n return masker.write(text) + masker.end()\n}\n\n/**\n * 执行外部命令,捕获与回调在UTF-8解码后以逻辑流为单位脱敏。\n * 无 shell 启动命令;stdout 回调接收按顺序脱敏的完整流,捕获结果仅保留有界尾部。超时后核验本地树退出;SSH 的远端状态由上层单独核对。\n * @param command - 可执行文件名或路径,不使用shell\n * @param args - 独立参数\n * @param options - 超时、输入、已知秘密及安全输出选项\n * @returns 失败返回REMOTE_COMMAND_FAILED;ext.commandExecution 记录终止核验,不暴露原始异常cause\n * @example 模块内部上下文\n * ```ts\n * const result = await runCommand(process.execPath, ['--version'], { timeoutMs: 5000, maxCaptureChars: 4096 })\n * if (!result.success) {\n * const { getDeployCommandState } = await import('../deploy-recovery.js')\n * const state = getDeployCommandState(result.error)\n * if (state?.localTermination === 'unknown') process.stderr.write('Local process-tree exit was not confirmed\\n')\n * }\n * else {\n * const output = result.data.stdout\n * }\n * ```\n */\nexport async function runCommand(command: string, args: string[], options: CommandOptions = {}): Promise<HaiResult<CommandResult>> {\n /** 失败状态只包含核验结论,不附加原始异常或可能携密的命令参数。 */\n const failure = (message: string, state: DeployCommandState): HaiResult<never> => err({\n ...HaiDeployError.REMOTE_COMMAND_FAILED,\n message: `${message}\\n${deployM(state.localTermination === 'confirmed' ? 'deploy_localStopped' : state.localTermination === 'not-started' ? 'deploy_localNotStarted' : 'deploy_localUnknown')}`,\n ext: { commandExecution: state },\n })\n try {\n return await new Promise((resolve) => {\n if (typeof command !== 'string' || !command || command.includes('\\0') || args.some(argument => typeof argument !== 'string' || argument.includes('\\0')))\n throw new TypeError('Invalid command arguments')\n if (options.input !== undefined && typeof options.input !== 'string')\n throw new TypeError('Invalid command input')\n const maxCapture = options.maxCaptureChars ?? 1048576\n if (!Number.isSafeInteger(maxCapture) || maxCapture <= 0 || maxCapture > 16777216)\n throw new RangeError('Invalid command capture limit')\n const terminationTimeout = options.terminationTimeoutMs ?? 10_000\n if (!Number.isSafeInteger(terminationTimeout) || terminationTimeout <= 0 || terminationTimeout > 60_000)\n throw new RangeError('Invalid command termination timeout')\n if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > 2147483647))\n throw new RangeError('Invalid command timeout')\n const secrets = [...(options.secrets ?? [])]\n const safeCommand = maskSecrets(command, secrets)\n const outputMasker = createSecretMasker(secrets)\n const errorMasker = createSecretMasker(secrets)\n const control = spawnCommand(command, args, { cwd: options.cwd, env: options.env ? { ...process.env, ...options.env } : process.env })\n const child = control.child\n child.stdout.setEncoding('utf8')\n child.stderr.setEncoding('utf8')\n let stdout = ''\n let stderr = ''\n let stdoutTruncated = false\n let stderrTruncated = false\n let settled = false\n let interrupted = false\n let interruption: Promise<void> | undefined\n let timer: NodeJS.Timeout | undefined\n const finish = (result: HaiResult<CommandResult>): void => {\n if (settled)\n return\n settled = true\n if (timer)\n clearTimeout(timer)\n resolve(result)\n }\n /** 先停止输出交付,再终止并等待整棵树;同一失败/close race 只结束一次。 */\n const interrupt = (reason: DeployCommandState['reason'], message: string): Promise<void> => {\n interrupted = true\n interruption ??= (async () => {\n if (timer)\n clearTimeout(timer)\n const localTermination = child.pid ? await control.terminate(terminationTimeout) : 'not-started'\n logger.error('Command termination checked', { command: safeCommand, reason, localTermination })\n finish(failure(message, { reason, localTermination }))\n })()\n return interruption\n }\n /** 所有捕获发生在脱敏后;流尾部状态和捕获长度均有上限。 */\n const publish = async (text: string): Promise<void> => {\n if (!text || settled || interrupted)\n return\n stdoutTruncated ||= stdout.length + text.length > maxCapture\n stdout = (stdout + text).slice(-maxCapture)\n try {\n await options.onOutput?.(text)\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n }\n const captureError = (text: string): void => {\n stderrTruncated ||= stderr.length + text.length > maxCapture\n stderr = (stderr + text).slice(-maxCapture)\n }\n if (options.timeoutMs && options.timeoutMs > 0) {\n timer = setTimeout(() => {\n logger.error('Command timed out', { command: safeCommand, timeoutMs: options.timeoutMs })\n // 异常结束不释放可能尚未完整的秘密尾部,也不再调用onOutput。\n void interrupt('timeout', deployM('deploy_commandTimeout', { params: { command: safeCommand } }))\n }, options.timeoutMs)\n }\n // 异步迭代器在等待回调期间保留pipe背压,不创建无限增长的Promise/输出队列。\n const outputTask = (async () => {\n try {\n for await (const chunk of child.stdout as AsyncIterable<unknown>) {\n if (settled || interrupted)\n return\n if (typeof chunk !== 'string')\n throw new TypeError('Command output must be UTF-8 decoded')\n await publish(outputMasker.write(chunk))\n }\n if (!settled && !interrupted)\n await publish(outputMasker.end())\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n })()\n const errorTask = (async () => {\n try {\n for await (const chunk of child.stderr as AsyncIterable<unknown>) {\n if (settled || interrupted)\n return\n if (typeof chunk !== 'string')\n throw new TypeError('Command error output must be UTF-8 decoded')\n captureError(errorMasker.write(chunk))\n }\n if (!settled && !interrupted)\n captureError(errorMasker.end())\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n })()\n child.stdin.on('error', () => {\n void interrupt('input', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandInputFailed') } }))\n })\n child.on('error', (error) => {\n const safeError = maskSecrets(error.message, secrets)\n logger.error('Command failed to start', { command: safeCommand, error: safeError })\n void interrupt('spawn', deployM('deploy_commandFailed', { params: { command: safeCommand, error: safeError } }))\n })\n child.on('close', async (code) => {\n await Promise.all([outputTask, errorTask])\n if (settled || interrupted)\n return\n if (timer)\n clearTimeout(timer)\n if (!(await control.treeExited())) {\n await interrupt('exit', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandTreeActive') } }))\n return\n }\n const exitCode = code ?? -1\n if (exitCode === 0) {\n finish(ok({ code: exitCode, stdout, stderr, stdoutTruncated, stderrTruncated }))\n return\n }\n logger.error('Command exited with non-zero code', { command: safeCommand, code: exitCode, stderr: maskSecrets(stderr, secrets).slice(-500), stdout: maskSecrets(stdout, secrets).slice(-3000), stdoutTruncated, stderrTruncated })\n finish(failure(deployM('deploy_commandFailed', { params: { command: safeCommand, error: maskSecrets(`${stdout.slice(-2500)}\\n${stderr || `exit ${exitCode}`}`, secrets).slice(-3000) } }), { reason: 'exit', localTermination: 'confirmed' }))\n })\n if (options.input !== undefined)\n child.stdin.write(options.input)\n child.stdin.end()\n })\n }\n catch {\n // 参数/正则编译/spawn同步错误可能携带原秘密,使用无cause的固定诊断失败关闭。\n return failure(deployM('deploy_commandFailed', { params: { command: '<command>', error: deployM('deploy_commandExecutionFailed') } }), { reason: 'configuration', localTermination: 'not-started' })\n }\n}\n","/** OpenSSH 的私有 askpass;固定 helper 无密码,凭据只在本次受管理子进程环境中存在。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { chmodSync, existsSync, lstatSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { runCommand } from './deploy-command.js'\n\n/**\n * 固定 C# 程序仅从环境读取密码,不含编译期或持久化凭据。\n * @example 模块内部上下文\n * ```ts\n * // sourceFile 由调用方在本次私有临时目录中分配;只落盘固定源码。\n * function writeWindowsSource(sourceFile: string): void {\n * writeFileSync(sourceFile, windowsAskpassSource, { mode: 0o600 })\n * }\n * ```\n */\nexport const windowsAskpassSource = String.raw`using System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Text;\nusing System.Threading;\npublic static class HaiDeployAskpass {\n public static int Main(string[] args) {\n if (args.Length >= 2 && args[0] == \"--run\") return Run(args);\n if (Environment.GetEnvironmentVariable(\"SSH_ASKPASS_PROMPT\") == \"confirm\") return 1;\n string value = Environment.GetEnvironmentVariable(\"HAI_DEPLOY_ASKPASS_PASSWORD\");\n if (String.IsNullOrEmpty(value) || value.IndexOfAny(new char[] { '\\r', '\\n', '\\0' }) >= 0 || Encoding.UTF8.GetByteCount(value) > 1023) return 1;\n Console.OutputEncoding = new UTF8Encoding(false);\n Console.Out.Write(value);\n Console.Out.Write(\"\\n\");\n return 0;\n }\n static string Quote(string value) {\n StringBuilder text = new StringBuilder(\"\\\"\");\n int slashes = 0;\n foreach (char character in value) {\n if (character == '\\\\') { slashes++; continue; }\n if (character == '\"') { text.Append('\\\\', slashes * 2 + 1).Append(character); slashes = 0; continue; }\n text.Append('\\\\', slashes).Append(character); slashes = 0;\n }\n return text.Append('\\\\', slashes * 2).Append('\"').ToString();\n }\n static void Pump(TextReader input, TextWriter output, string secret) {\n char[] buffer = new char[4096];\n StringBuilder pending = new StringBuilder();\n int count;\n while ((count = input.Read(buffer, 0, buffer.Length)) > 0) {\n pending.Append(buffer, 0, count);\n while (pending.Length >= secret.Length) {\n bool matches = true;\n for (int i = 0; i < secret.Length; i++) if (pending[i] != secret[i]) { matches = false; break; }\n if (matches) { output.Write(\"***\"); pending.Remove(0, secret.Length); }\n else { output.Write(pending[0]); pending.Remove(0, 1); }\n }\n output.Flush();\n }\n output.Write(pending.ToString()); output.Flush();\n }\n static int Run(string[] args) {\n try {\n string secret = Environment.GetEnvironmentVariable(\"HAI_DEPLOY_ASKPASS_PASSWORD\");\n if (String.IsNullOrEmpty(secret)) return 1;\n ProcessStartInfo start = new ProcessStartInfo();\n start.FileName = args[1]; start.UseShellExecute = false; start.CreateNoWindow = true;\n start.RedirectStandardOutput = true; start.RedirectStandardError = true;\n start.StandardOutputEncoding = new UTF8Encoding(false); start.StandardErrorEncoding = new UTF8Encoding(false);\n StringBuilder arguments = new StringBuilder();\n for (int i = 2; i < args.Length; i++) { if (i > 2) arguments.Append(' '); arguments.Append(Quote(args[i])); }\n start.Arguments = arguments.ToString();\n using (Process child = Process.Start(start)) {\n Thread stdout = new Thread(() => Pump(child.StandardOutput, Console.Out, secret));\n Thread stderr = new Thread(() => Pump(child.StandardError, Console.Error, secret));\n stdout.Start(); stderr.Start(); child.WaitForExit(); stdout.Join(); stderr.Join(); return child.ExitCode;\n }\n } catch { Console.Error.WriteLine(\"SSH command failed.\"); return 1; }\n }\n}\n`\n\n/**\n * POSIX helper 只输出环境原值;主机信任确认不应由密码代答。\n * @example 模块内部上下文\n * ```ts\n * // helperFile 位于本次私有临时目录;密码由执行时的 child env 提供。\n * function writePosixHelper(helperFile: string): void {\n * writeFileSync(helperFile, posixAskpassSource, { mode: 0o700 })\n * }\n * ```\n */\nexport const posixAskpassSource = String.raw`#!/bin/sh\ntest \"\\${SSH_ASKPASS_PROMPT:-}\" != confirm || exit 1\ntest -n \"\\${HAI_DEPLOY_ASKPASS_PASSWORD:-}\" || exit 1\nprintf '%s\\n' \"$HAI_DEPLOY_ASKPASS_PASSWORD\"\n`.replaceAll('\\\\${', '${')\n\n/**\n * Windows PowerShell 5/.NET Framework 编译;不使用不支持原生 ConsoleApplication 的 pwsh。\n * @example 模块内部上下文\n * ```ts\n * // compiler 是系统 Windows PowerShell 5;两个文件路径均由本次私有目录分配。\n * async function compileHelper(compiler: string, sourceFile: string, outputFile: string) {\n * const compiled = await runCommand(compiler, ['-NoProfile', '-NonInteractive', '-Command', compileAskpassScript], {\n * env: { HAI_DEPLOY_ASKPASS_SOURCE: sourceFile, HAI_DEPLOY_ASKPASS_OUTPUT: outputFile, HAI_DEPLOY_ASKPASS_PASSWORD: '' },\n * timeoutMs: 30000,\n * })\n * if (!compiled.success) return compiled\n * return ok(undefined)\n * }\n * ```\n */\nexport const compileAskpassScript = '$ErrorActionPreference=\\'Stop\\'; Add-Type -Language CSharp -TypeDefinition ([System.IO.File]::ReadAllText($env:HAI_DEPLOY_ASKPASS_SOURCE, [System.Text.Encoding]::UTF8)) -OutputType ConsoleApplication -OutputAssembly $env:HAI_DEPLOY_ASKPASS_OUTPUT'\n\n/**\n * 本次 helper 的受控环境与清理操作;目录只属于当前命令调用。\n * @example 模块内部上下文\n * ```ts\n * function finishHelper(helper: SshAskpass): HaiResult<void> {\n * const removed = helper.cleanup()\n * if (!removed.success) return removed\n * return ok(undefined)\n * }\n * ```\n */\nexport interface SshAskpass {\n env: Record<string, string>\n cleanup: () => HaiResult<void>\n}\n\n/** 不传播可能包含输入的异常;本地准备失败尚未开始 SSH 远端操作。 */\nfunction helperFailure(key: 'deploy_sshAskpassFailed' | 'deploy_sshAskpassCleanupFailed', reason: 'configuration' | 'timeout' = 'configuration'): HaiResult<never> {\n return err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM(key), ext: { commandExecution: { reason, localTermination: 'not-started' } } })\n}\n\n/**\n * 为一次命令准备无秘密 helper;准备时间包含在调用者的绝对单调时钟 deadline 内。\n * @param password - 已校验、保持空格和 Unicode 的密码原值。\n * @param deadline - performance.now() 的绝对毫秒期限;Infinity 表示命令没有整体期限。\n * @param terminationTimeoutMs - 原受管理进程树终止核验预算。\n * @returns 固定 helper 环境及清理函数;失败不暴露原异常或降级交互输入。\n * @example 模块内部上下文\n * ```ts\n * async function inspectPreparedHelper(password: string) {\n * const prepared = await prepareSshAskpass(password, performance.now() + 20000)\n * if (!prepared.success) return prepared\n * const askpassMode = prepared.data.env.SSH_ASKPASS_REQUIRE\n * const removed = prepared.data.cleanup()\n * if (!removed.success) return removed\n * return ok(askpassMode)\n * }\n * ```\n */\nexport async function prepareSshAskpass(password: string, deadline: number, terminationTimeoutMs?: number): Promise<HaiResult<SshAskpass>> {\n let directory: string | undefined\n let temporaryRoot: string | undefined\n const cleanup = (): HaiResult<void> => {\n if (!directory || !existsSync(directory))\n return ok(undefined)\n try {\n if (lstatSync(directory).isSymbolicLink() || dirname(realpathSync(directory)) !== temporaryRoot || !basename(directory).startsWith('hai-ssh-askpass-'))\n return helperFailure('deploy_sshAskpassCleanupFailed')\n rmSync(directory, { recursive: true, force: false })\n return ok(undefined)\n }\n catch { return helperFailure('deploy_sshAskpassCleanupFailed') }\n }\n try {\n temporaryRoot = realpathSync(tmpdir())\n if (deadline <= performance.now())\n return helperFailure('deploy_sshAskpassFailed', 'timeout')\n if (!password || /[\\r\\n\\0]/.test(password) || new TextEncoder().encode(password).length > 1023)\n return helperFailure('deploy_sshAskpassFailed')\n directory = mkdtempSync(join(temporaryRoot, 'hai-ssh-askpass-'))\n chmodSync(directory, 0o700)\n let helper = join(directory, 'askpass.sh')\n if (process.platform === 'win32') {\n helper = join(directory, 'askpass.exe')\n const source = join(directory, 'askpass.cs')\n writeFileSync(source, windowsAskpassSource, { mode: 0o600 })\n const compiler = join(process.env.SystemRoot ?? 'C:\\\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')\n const compiled = await runCommand(compiler, ['-NoProfile', '-NonInteractive', '-Command', compileAskpassScript], {\n env: { HAI_DEPLOY_ASKPASS_SOURCE: source, HAI_DEPLOY_ASKPASS_OUTPUT: helper, HAI_DEPLOY_ASKPASS_PASSWORD: '' },\n timeoutMs: Math.max(1, Math.min(30_000, Math.ceil(deadline - performance.now()))),\n terminationTimeoutMs,\n secrets: [password],\n })\n if (!compiled.success) {\n const removed = cleanup()\n return removed.success ? compiled : removed\n }\n if (!existsSync(helper)) {\n const removed = cleanup()\n return removed.success ? helperFailure('deploy_sshAskpassFailed') : removed\n }\n }\n else {\n writeFileSync(helper, posixAskpassSource, { mode: 0o700 })\n }\n if (deadline <= performance.now()) {\n const removed = cleanup()\n return removed.success ? helperFailure('deploy_sshAskpassFailed', 'timeout') : removed\n }\n return ok({ env: { SSH_ASKPASS: helper, SSH_ASKPASS_REQUIRE: 'force', SSH_ASKPASS_PROMPT: '', DISPLAY: 'hai-deploy:0', HAI_DEPLOY_ASKPASS_PASSWORD: password }, cleanup })\n }\n catch {\n const removed = cleanup()\n return removed.success ? helperFailure('deploy_sshAskpassFailed') : removed\n }\n}\n","/**\n * 生成独立 JSON 读取器;上传脚本仅需 POSIX awk,无 Node 或 jq 依赖。\n * @returns 可作为部署包 read-target.awk 文件内容的 POSIX awk 程序。\n * @example 模块内部上下文\n * ```ts\n * const reader: string = createTargetReader()\n * // 将 reader 写入部署包,由上传脚本读取 deploy-target.json 中的目标配置。\n * ```\n */\nexport function createTargetReader(): string {\n return String.raw`function fail(message) {\n print \"Invalid deploy-target.json: \" message > \"/dev/stderr\"\n exit 2\n}\nfunction whitespace() {\n while (substr(input, position, 1) ~ /^[ \\t\\r\\n]$/) position++\n}\nfunction hexadecimal(text, result, offset, digit) {\n result = 0\n if (length(text) != 4) fail(\"invalid Unicode escape\")\n for (offset = 1; offset <= 4; offset++) {\n digit = index(\"0123456789abcdef\", tolower(substr(text, offset, 1))) - 1\n if (digit < 0) fail(\"invalid Unicode escape\")\n result = result * 16 + digit\n }\n return result\n}\nfunction utf8(code) {\n if (code < 128) return sprintf(\"%c\", code)\n if (code < 2048) return sprintf(\"%c%c\", 192 + int(code / 64), 128 + code % 64)\n if (code < 65536) return sprintf(\"%c%c%c\", 224 + int(code / 4096), 128 + int(code / 64) % 64, 128 + code % 64)\n return sprintf(\"%c%c%c%c\", 240 + int(code / 262144), 128 + int(code / 4096) % 64, 128 + int(code / 64) % 64, 128 + code % 64)\n}\nfunction string_value( result, character, escaped, code, low) {\n if (substr(input, position++, 1) != \"\\\"\") fail(\"expected string\")\n result = \"\"\n while (position <= length(input)) {\n character = substr(input, position++, 1)\n if (character == \"\\\"\") return result\n if (character ~ /[[:cntrl:]]/) fail(\"control character in string\")\n if (character != \"\\\\\") { result = result character; continue }\n escaped = substr(input, position++, 1)\n if (escaped == \"\\\"\" || escaped == \"\\\\\" || escaped == \"/\") result = result escaped\n else if (escaped == \"b\") result = result sprintf(\"%c\", 8)\n else if (escaped == \"f\") result = result sprintf(\"%c\", 12)\n else if (escaped == \"n\") result = result \"\\n\"\n else if (escaped == \"r\") result = result \"\\r\"\n else if (escaped == \"t\") result = result \"\\t\"\n else if (escaped == \"u\") {\n code = hexadecimal(substr(input, position, 4)); position += 4\n if (code >= 55296 && code <= 56319) {\n if (substr(input, position, 2) != \"\\\\u\") fail(\"missing low surrogate\")\n position += 2\n low = hexadecimal(substr(input, position, 4)); position += 4\n if (low < 56320 || low > 57343) fail(\"invalid low surrogate\")\n code = 65536 + (code - 55296) * 1024 + low - 56320\n } else if (code >= 56320 && code <= 57343) fail(\"unexpected low surrogate\")\n if (code == 0) fail(\"NUL is not allowed\")\n result = result utf8(code)\n } else fail(\"invalid escape\")\n }\n fail(\"unterminated string\")\n}\nfunction object_value(depth, key, character, value, kind) {\n if (depth > 16) fail(\"nesting is too deep\")\n position++\n whitespace()\n if (substr(input, position, 1) == \"}\") { position++; return }\n while (position <= length(input)) {\n whitespace(); key = string_value(); whitespace()\n if (substr(input, position++, 1) != \":\") fail(\"expected colon\")\n whitespace(); character = substr(input, position, 1)\n if (character == \"{\") { object_value(depth + 1); value = \"\"; kind = \"object\" }\n else if (character == \"\\\"\") { value = string_value(); kind = \"string\" }\n else if (substr(input, position, 4) == \"true\") { value = \"true\"; kind = \"boolean\"; position += 4 }\n else if (substr(input, position, 5) == \"false\") { value = \"false\"; kind = \"boolean\"; position += 5 }\n else if (substr(input, position, 4) == \"null\") { value = \"\"; kind = \"null\"; position += 4 }\n else if (match(substr(input, position), /^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?/)) {\n value = substr(input, position, RLENGTH); position += RLENGTH; kind = \"number\"\n } else fail(\"unsupported value\")\n if (depth == 1) {\n if (key in values) fail(\"duplicate field: \" key)\n values[key] = value; kinds[key] = kind\n }\n whitespace(); character = substr(input, position++, 1)\n if (character == \"}\") return\n if (character != \",\") fail(\"expected comma or closing brace\")\n }\n fail(\"unterminated object\")\n}\n{ input = input $0 \"\\n\" }\nEND {\n position = 1\n if (substr(input, 1, 3) == sprintf(\"%c%c%c\", 239, 187, 191)) position = 4\n whitespace()\n if (substr(input, position, 1) != \"{\") fail(\"expected object\")\n object_value(1); whitespace()\n if (position <= length(input)) fail(\"trailing content\")\n if (!(field in values) || kinds[field] == \"null\") { print fallback; exit }\n if (kinds[field] != expected) fail(\"wrong type for \" field)\n if (values[field] ~ /[[:cntrl:]]/) fail(\"control character in \" field)\n print values[field]\n}\n`\n}\n","/** 在线发布与手工交付共用的服务器执行脚本。远程依赖 Linux flock、基础工具及 Compose。 */\nimport { deployM } from '../deploy-i18n.js'\nimport { createComposeContainerLookupScript } from './deploy-compose-identity.js'\nimport { windowsAskpassSource } from './deploy-ssh-askpass.js'\nimport { createTargetReader } from './deploy-target.js'\n\n/**\n * 将可信配置编码为一个 shell 参数。\n * @param value - 受信值,编码为一个远端 shell 参数。\n * @returns 可作为一个远端 shell 参数的编码文本。\n * @example 模块内部上下文\n * ```ts\n * const encoded = shellArgument(\"Shop's app\") // 整体作为一个远端 shell 参数。\n * ```\n */\nexport function shellArgument(value: string): string {\n return `'${value.replaceAll('\\'', '\\'\"\\'\"\\'')}'`\n}\n\n/**\n * 生成分步执行、增量合并和失败恢复脚本;密钥始终从环境文件读取。\n * 仅生成 Linux 脚本;正常收尾显式释放 FD9 flock,中断时由仍持有描述符的进程树维持。未知旧锁目录不删除,结果仅由取得锁的 owner 发布。\n * @param options - 本次操作选项;字段含义见各子项。\n * @param options.deploymentId - 本次不可变部署标识,用于结果匹配和发布目录。\n * @param options.projectName - 已归一化的项目名称。\n * @param options.environment - 部署环境标识,通常为 prod。\n * @param options.directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @param options.runtime - 容器引擎策略;auto 探测可用引擎并优先 Podman。\n * @param options.partial - 是否为增量服务部署;不能据此执行首次全量安装。\n * @param options.selected - 本次选择更新的 Compose 服务。\n * @param options.hostPort - 宿主公开端口。\n * @param options.healthPaths - 允许执行的应用健康检查路径。\n * @param options.primaryService - 主运行服务角色,用于定位私有运行环境与启动提示。\n * @returns 待在 Linux 远端运行的 apply 脚本文本。\n * @example 模块内部上下文\n * ```ts\n * const script = createApplyScript({ deploymentId: 'shop-prod-001', projectName: 'shop-prod', environment: 'prod', directory: '/opt/hai/apps/shop-prod', runtime: 'auto', partial: false, selected: ['serv'], hostPort: 8080, healthPaths: ['/health'] })\n * ```\n */\nexport function createApplyScript(options: {\n deploymentId: string\n projectName: string\n environment: string\n directory: string\n runtime: 'auto' | 'docker' | 'podman'\n partial: boolean\n selected: string[]\n hostPort: number\n healthPaths: string[]\n primaryService?: 'serv' | 'web'\n}): string {\n const values: Record<string, string> = {\n ID: shellArgument(options.deploymentId),\n PROJECT: shellArgument(`hai-${options.projectName}`),\n ENV: shellArgument(options.environment),\n RUNTIME: shellArgument(options.runtime),\n PARTIAL: options.partial ? 'true' : 'false',\n SELECTED: shellArgument(options.selected.join(' ')),\n ROOT: shellArgument(options.directory),\n PORT: String(options.hostPort),\n HEALTH: options.healthPaths.map(shellArgument).join(' '),\n PRIMARY: options.primaryService ?? 'serv',\n LOOKUP: createComposeContainerLookupScript(),\n }\n return String.raw`#!/bin/sh\n# 服务器部署流程:由 deploy-local.sh 或 SSH 入口自动解包后调用,无需手工解包。\n# 需要 Linux、sha256sum、tar、awk、curl、flock 和可用的 Docker/Podman Compose;不会联网拉镜像。\n# 本次全量/增量及服务清单由生成时的 manifest.json 和下方 partial/selected 固定。\n# 增量要求服务器已有成功的全量基线;校验失败不会开始替换服务,失败恢复保留数据卷。\nset -eu\numask 077\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\ndestination=@@ROOT@@\nif [ \"$#\" -gt 0 ]; then destination=$1; fi\nroot=$(mkdir -p -- \"$destination\" && CDPATH= cd -- \"$destination\" && pwd)\nid=@@ID@@\nproject=@@PROJECT@@\nexport HAI_DEPLOY_ENVIRONMENT=@@ENV@@\nruntime=@@RUNTIME@@\npartial=@@PARTIAL@@\norphan_option=''\nif [ \"$partial\" = false ]; then orphan_option=--remove-orphans; fi\nrecreate_option=--force-recreate\nif [ \"$partial\" = true ]; then recreate_option=--no-recreate; fi\nselected=@@SELECTED@@\nproxy_update=false\nrelease=\"$root/releases/$id\"\ncase \"$release/\" in \"$source_dir/\"*) printf 'Extract the package outside the deployment directory before applying it.\\n' >&2; exit 1;; esac\nstage=''\nprevious=''\nrestore=''\nchanged=false\nimages_changed=false\nrecovery_status=not-needed\nlocked=false\nresult_owned=false\ninterrupted=false\nstarted=$(date +%s)\nstep_started=$started\n@@LOOKUP@@\nstep() {\n if [ -n \"$stage\" ] && [ \"$result_owned\" = true ]; then\n duration=$(( $(date +%s) - step_started ))\n printf '[PASS] %s (%ss)\\n' \"$stage\" \"$duration\"\n printf '{\"stage\":\"%s\",\"status\":\"passed\",\"durationSeconds\":%s}\\n' \"$stage\" \"$duration\" >> \"$root/steps-$id.jsonl\"\n fi\n stage=\"$1\"\n step_started=$(date +%s)\n printf '\\n[%s] %s\\n' \"$stage\" \"$2\"\n}\ncompose() {\n arguments_file=\"$release/compose-files\"\n if [ -n \"$restore\" ]; then arguments_file=\"$root/releases/$restore/compose-files\"; fi\n # -f 按顺序合并,由 Compose 保留未选服务、卷和环境文件,不自行拼装配置。\n command_args=\"$release/.compose-command\"\n # 文件列表先反向读取,再向参数头部加入,保留原始合并顺序。\n awk '{lines[NR]=$0} END {for(i=NR;i>0;i--) print lines[i]}' \"$arguments_file\" > \"$command_args\"\n while IFS= read -r file; do set -- -f \"$file\" \"$@\"; done < \"$command_args\"\n \"$runtime\" compose -p \"$project\" \"$@\"\n}\nremove_selected() {\n test \"$partial\" = true || return 0\n # 直接替换选中容器,避免 Compose Provider 连带重建依赖它的未选服务;不删除卷。\n for service in \"$@\"; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -aq) || return 1\n for container in $containers; do\n \"$runtime\" rm -f \"$container\" || return 1\n done\n done\n}\nwait_services() {\n for waiting_service in \"$@\"; do\n ready=false\n attempt=0\n while [ \"$attempt\" -lt 60 ]; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$waiting_service\" -q) || return 1\n test -n \"$containers\" || { printf 'Service %s is not running. Inspect its startup diagnostics.\\n' \"$waiting_service\" >&2; return 1; }\n ready=true\n for container in $containers; do\n running=$(\"$runtime\" inspect --format '{{.State.Running}}' \"$container\") || return 1\n test \"$running\" = true || { printf 'Service %s stopped during startup.\\n' \"$waiting_service\" >&2; return 1; }\n health=$(\"$runtime\" inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' \"$container\") || return 1\n # 独立 Podman 可能没有 systemd 调度;主动探测后重读状态,失败不能放行业务。\n case \"$runtime:$health\" in\n podman:starting|podman:unhealthy|podman:healthy)\n probe_ready=false\n if \"$runtime\" healthcheck run \"$container\" >/dev/null 2>&1; then probe_ready=true; fi\n health=$(\"$runtime\" inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' \"$container\") || return 1\n # 当前探测失败不能依赖旧 healthy 状态放行。\n if [ \"$probe_ready\" != true ] && [ \"$health\" = healthy ]; then health=starting; fi\n ;;\n esac\n case \"$health\" in\n healthy|none) ;;\n unhealthy) printf 'Service %s is unhealthy. Inspect its startup diagnostics.\\n' \"$waiting_service\" >&2; return 1;;\n *) ready=false;;\n esac\n done\n if [ \"$ready\" = true ]; then break; fi\n attempt=$((attempt + 1))\n sleep 2\n done\n test \"$ready\" = true || { printf 'Service %s did not become ready before the startup deadline.\\n' \"$waiting_service\" >&2; return 1; }\n done\n}\nstart_services() {\n middleware_services=''\n application_services=''\n application_orphan_option=$orphan_option\n for service in \"$@\"; do\n case \"$service\" in serv|web|gateway|certbot) ;; *) middleware_services=\"$middleware_services $service\";; esac\n done\n if [ -n \"$middleware_services\" ]; then\n compose up -d --no-deps --no-build --pull never \"$recreate_option\" $orphan_option $middleware_services || return 1\n wait_services $middleware_services || return 1\n # Podman Compose 按本批服务清理孤立容器;后批不能删除已经就绪的中间件。\n application_orphan_option=''\n fi\n # --no-deps 保留未选容器;先等本次中间件就绪,再启动应用和依赖它的 Web。\n case \" $* \" in *' serv '*) application_services=serv;; esac\n case \" $* \" in *' web '*) application_services=\"$application_services web\";; esac\n if [ -n \"$application_services\" ]; then\n compose up -d --no-deps --no-build --pull never \"$recreate_option\" $application_orphan_option $application_services || return 1\n fi\n case \" $* \" in *' gateway '*) compose up -d --no-deps --no-build --pull never \"$recreate_option\" gateway || return 1;; esac\n}\nstart_renewal() {\n case \" $* \" in *' certbot '*) compose up -d --no-deps --no-build --pull never --no-recreate certbot || return 1;; esac\n}\nread_proxy_service() {\n proxy_directory=$1\n if [ -e \"$proxy_directory/proxy-service\" ] || [ -L \"$proxy_directory/proxy-service\" ]; then\n test -f \"$proxy_directory/proxy-service\" && test ! -L \"$proxy_directory/proxy-service\" || return 1\n stored_proxy=$(cat \"$proxy_directory/proxy-service\") || return 1\n else\n stored_proxy=$(awk -F: 'NR == 1 { if ($3 == \"true\") print \"web\"; else if ($3 == \"gateway\") print \"gateway\"; }' \"$proxy_directory/layout\") || return 1\n fi\n case \"$stored_proxy\" in ''|web|gateway) printf '%s' \"$stored_proxy\";; *) return 1;; esac\n}\nreload_retained_proxy() {\n retained_proxy=$(read_proxy_service \"$1\") || return 1\n test -n \"$retained_proxy\" || return 0\n # Nginx 静态 upstream 会保留旧容器 IP;应用或存储增量替换后重新解析服务 DNS。\n case \" $selected \" in *' serv '*|*' web '*|*' storage '*)\n case \" $selected \" in *\" $retained_proxy \"*) ;; *)\n if grep -qx \"$retained_proxy\" \"$1/services\"; then compose exec -T \"$retained_proxy\" nginx -s reload || return 1; fi\n ;;\n esac\n ;;\n esac\n}\nwait_http() {\n http_release=$1\n http_port=$2\n shift 2\n https_domain=''\n if [ -f \"$http_release/https\" ]; then\n read -r https_domain https_port https_type < \"$http_release/https\"\n https_certificates=\"$http_release/tls\"\n if [ \"$https_type\" = letsencrypt ]; then https_certificates=\"$root/https/certificates/$https_domain\"; fi\n fi\n for http_path in \"$@\"; do\n http_ready=false\n http_attempt=0\n while [ \"$http_attempt\" -lt 40 ]; do\n if [ -n \"$https_domain\" ]; then\n if curl --noproxy '*' -fsS --max-time 5 --cacert \"$https_certificates/fullchain.pem\" --resolve \"$https_domain:$https_port:127.0.0.1\" \"https://$https_domain:$https_port$http_path\" >/dev/null 2>&1; then http_ready=true; break; fi\n elif curl --noproxy '*' -fsS --max-time 5 \"http://127.0.0.1:$http_port$http_path\" >/dev/null 2>&1; then http_ready=true; break; fi\n http_attempt=$((http_attempt + 1))\n sleep 3\n done\n test \"$http_ready\" = true || { printf 'HTTP check failed: %s. Inspect compose logs for selected services.\\n' \"$http_path\" >&2; return 1; }\n done\n}\nverify_recovery() {\n # 回滚使用旧发布的端口与探测路径,不能用失败新包的地址证明旧服务健康。\n recovery_release=\"$root/releases/$previous\"\n recovery_port=$(awk -F: 'NR == 1 { print $1 }' \"$recovery_release/layout\") || return 1\n recovery_paths=''\n if [ -f \"$recovery_release/health-paths\" ]; then\n recovery_paths=$(cat \"$recovery_release/health-paths\") || return 1\n else\n # 旧格式发布没有独立健康文件;按已存拓扑恢复最小 HTTP 检查。\n recovery_proxy=$(awk -F: 'NR == 1 { print $3 }' \"$recovery_release/layout\") || return 1\n recovery_primary=$(awk -F: 'NR == 1 { print $4 }' \"$recovery_release/layout\") || return 1\n if [ \"$recovery_proxy\" = true ]; then recovery_paths='/health /_hai/web-health /';\n elif [ \"$recovery_primary\" = web ]; then recovery_paths='/'; else recovery_paths='/health'; fi\n fi\n case \"$recovery_port\" in ''|*[!0-9]*) return 1;; esac\n wait_services $recover_selected || return 1\n start_renewal $recover_selected || return 1\n reload_retained_proxy \"$recovery_release\" || return 1\n wait_http \"$recovery_release\" \"$recovery_port\" $recovery_paths\n}\nfinish() {\n code=$?\n trap - EXIT HUP INT TERM\n if [ \"$code\" -ne 0 ]; then\n printf '[FAIL] %s (exit %s)\\n' \"$stage\" \"$code\" >&2\n if [ \"$changed\" = true ]; then\n diagnostics=\"$root/diagnostics-$id.log\"\n : > \"$diagnostics\"\n for service in $selected; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -aq || true)\n for container in $containers; do\n \"$runtime\" inspect --format '{{.Name}} {{.State.Status}} exit={{.State.ExitCode}}' \"$container\" >> \"$diagnostics\" 2>&1 || true\n \"$runtime\" logs --tail 80 \"$container\" >> \"$diagnostics\" 2>&1 || true\n done\n done\n printf 'Startup diagnostics saved to %s (private server file).\\n' \"$diagnostics\" >&2\n fi\n # 只有本次实际开始导入镜像才能恢复标签;重复 ID/校验失败不能重放历史恢复记录。\n if [ \"$images_changed\" = true ] && [ -f \"$release/rollback-images\" ]; then\n while IFS=' ' read -r image reference; do\n test -n \"$reference\" || continue\n if ! \"$runtime\" tag \"$image\" \"$reference\"; then\n recovery_status=failed\n printf '[FAIL] Cannot restore image %s\\n' \"$reference\" >&2\n fi\n done < \"$release/rollback-images\"\n fi\n if [ \"$changed\" = true ] && [ -n \"$previous\" ]; then\n printf '[RECOVER] Restoring previous selected services\\n' >&2\n recover_selected=$selected\n if [ \"$partial\" = false ]; then recover_selected=$(cat \"$root/releases/$previous/services\"); fi\n restore=\"$previous\"\n if sh \"$release/resolve-backend-state.sh\" \"$root\" \"$release\" \"$runtime\" \"$previous\" recover && remove_selected $recover_selected && start_services $recover_selected && verify_recovery && [ \"$recovery_status\" != failed ]; then\n recovery_status=passed\n printf '[RECOVER] Previous release passed recovery health checks\\n' >&2\n else\n recovery_status=failed\n printf '[FAIL] Recovery failed. Use the previous release and inspect container logs.\\n' >&2\n fi\n elif [ \"$changed\" = true ]; then\n if compose stop $selected; then\n recovery_status=stopped\n printf '[RECOVER] Failed first installation stopped; data volumes retained\\n' >&2\n else\n recovery_status=failed\n printf '[FAIL] Could not stop failed first installation; inspect containers.\\n' >&2\n fi\n fi\n fi\n if [ \"$locked\" = true ]; then\n if [ \"$result_owned\" = true ]; then\n elapsed=$(( $(date +%s) - started ))\n outcome=passed\n if [ \"$code\" -ne 0 ]; then outcome=failed; fi\n printf '{\"stage\":\"%s\",\"status\":\"%s\",\"durationSeconds\":%s}\\n' \"$stage\" \"$outcome\" \"$(( $(date +%s) - step_started ))\" >> \"$root/steps-$id.jsonl\"\n # 先完整写入再同目录原子发布,SSH 重连核对不能读取到半份终态结果。\n printf '{\"deploymentId\":\"%s\",\"stage\":\"%s\",\"exitCode\":%s,\"durationSeconds\":%s,\"recoveryStatus\":\"%s\"}\\n' \"$id\" \"$stage\" \"$code\" \"$elapsed\" \"$recovery_status\" > \"$root/result-$id.json.next\"\n mv \"$root/result-$id.json.next\" \"$root/result-$id.json\"\n fi\n # 前台命令及同步恢复已结束;后台服务可继续运行,但不能使成功终态永久占锁。\n # 中断时仍可能有活跃子命令,必须由全部描述符持有者退出后释放。\n if [ \"$interrupted\" = false ]; then\n flock -u 9\n exec 9>&-\n fi\n fi\n exit \"$code\"\n}\ntrap finish EXIT\ntrap 'interrupted=true; exit 130' HUP INT TERM\nstep preflight 'Checking deployment tools and package'\nfor tool in sha256sum tar awk curl flock; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\nif [ \"$runtime\" = auto ]; then\n if command -v podman >/dev/null 2>&1 && podman version >/dev/null 2>&1; then runtime=podman; else runtime=docker; fi\nfi\ncase \"$runtime\" in docker|podman) ;; *) printf 'Runtime must be docker or podman\\n' >&2; exit 1;; esac\n\"$runtime\" version >/dev/null\n\"$runtime\" compose version >/dev/null\n\"$runtime\" compose up --help | grep -q never || { printf 'Compose is too old. Install Docker Compose v2 or podman-compose 1.6.0 or newer (supports --pull never).\\n' >&2; exit 1; }\n# 内核锁绑定同一文件描述符;绝不删除/替换锁文件,避免新 inode 绕过活跃部署。\n# 子命令继承 FD 9:即使父 shell 被强杀,仍执行的命令继续持锁;全部退出或重启后自动释放。\nexec 9>\"$root/.deploy.lock\"\nif flock -n 9; then\n :\nelse\n lock_code=$?\n if [ \"$lock_code\" -eq 1 ]; then\n printf 'Another deployment is running. Wait for its commands to finish; do not remove %s/.deploy.lock.\\n' \"$root\" >&2\n else\n printf 'Cannot acquire deployment lock (exit %s). Check filesystem flock support and permissions.\\n' \"$lock_code\" >&2\n fi\n exit \"$lock_code\"\nfi\nlocked=true\n# 已使用或中断留下的 ID 不能重新认领,尤其不能覆盖原终态和步骤证据。\nif [ -e \"$release\" ] || [ -L \"$release\" ] || [ -e \"$root/result-$id.json\" ] || [ -L \"$root/result-$id.json\" ] || [ -e \"$root/steps-$id.jsonl\" ] || [ -L \"$root/steps-$id.jsonl\" ] || [ -e \"$root/result-$id.json.next\" ] || [ -L \"$root/result-$id.json.next\" ]; then\n printf 'This deployment ID was already used. Create a new deployment bundle.\\n' >&2\n exit 1\nfi\nresult_owned=true\ncd \"$source_dir\"\nsha256sum -c SHA256SUMS\nif [ -f \"$root/current\" ]; then\n previous=$(cat \"$root/current\")\n case \"$previous\" in ''|*[!a-zA-Z0-9._-]*) printf 'Invalid deployment state\\n' >&2; exit 1;; esac\n test -f \"$root/releases/$previous/compose-files\"\nfi\n# 独立持久账本覆盖暂时移除的服务和首次失败留下的卷,预检不写状态。\nsh \"$source_dir/resolve-backend-state.sh\" \"$root\" \"$source_dir\" \"$runtime\" \"$previous\" check\nif [ \"$partial\" = true ]; then\n test -n \"$previous\" || { printf 'Partial deployment requires a successful full installation. Deploy a complete bundle first.\\n' >&2; exit 1; }\n # 目录属于完整Web拓扑;旧版本缺省为根目录,服务增量不能意外丢失或改变既有目录。\n read_deployment_metadata() {\n if [ -e \"$1\" ] || [ -L \"$1\" ]; then\n test -f \"$1\" && test ! -L \"$1\" || { printf 'Deployment path/config metadata must be a regular file.\\n' >&2; return 1; }\n cat \"$1\"\n fi\n }\n current_web_base=$(read_deployment_metadata \"$source_dir/web-base-path\")\n previous_web_base=$(read_deployment_metadata \"$root/releases/$previous/web-base-path\")\n test \"$current_web_base\" = \"$previous_web_base\" || { printf 'Web base path changed. Match the installed prefix for partial updates, or create a full deployment.\\n' >&2; exit 1; }\n current_storage_routing=$(read_deployment_metadata \"$source_dir/storage-routing\")\n previous_storage_routing=$(read_deployment_metadata \"$root/releases/$previous/storage-routing\")\n test \"$current_storage_routing\" = \"$previous_storage_routing\" || { printf 'Managed storage configuration changed. Create a full deployment to switch its public endpoint, bucket, or access policy consistently.\\n' >&2; exit 1; }\n if ! cmp -s layout \"$root/releases/$previous/layout\"; then\n # 容量调整允许复用已部署 Web 镜像;端口、路由及其余代理策略仍要求全量部署。\n test \"$(awk -F: '{print $1 \":\" $2 \":\" $3 \":\" $4 \":\" $6}' layout)\" = \"$(awk -F: '{print $1 \":\" $2 \":\" $3 \":\" $4 \":\" $6}' \"$root/releases/$previous/layout\")\" || { printf 'Ports, HTTPS or application layout changed. Create a full deployment bundle.\\n' >&2; exit 1; }\n test -f web.conf && test -f proxy-entry.json || { printf 'Proxy configuration missing. Create a full deployment bundle.\\n' >&2; exit 1; }\n previous_proxy=\n while IFS= read -r compose_file; do\n candidate_proxy=\"$(dirname -- \"$compose_file\")/web.conf\"\n if [ -f \"$candidate_proxy\" ]; then previous_proxy=$candidate_proxy; fi\n done < \"$root/releases/$previous/compose-files\"\n test -n \"$previous_proxy\" || { printf 'Proxy baseline missing. Create a full deployment bundle.\\n' >&2; exit 1; }\n previous_shape=$(sed 's/client_max_body_size [0-9][0-9]*;/client_max_body_size TRANSPORT;/' \"$previous_proxy\" | sha256sum)\n current_shape=$(sed 's/client_max_body_size [0-9][0-9]*;/client_max_body_size TRANSPORT;/' web.conf | sha256sum)\n test \"$previous_shape\" = \"$current_shape\" || { printf 'API routes or proxy policy changed. Create a full deployment bundle.\\n' >&2; exit 1; }\n case \" $selected \" in *' @@PRIMARY@@ '*) ;; *) printf 'Transport capacity changes require the primary application service. Include it in the partial deployment.\\n' >&2; exit 1;; esac\n current_proxy=$(read_proxy_service \"$source_dir\") || exit 1\n test -n \"$current_proxy\" || { printf 'Proxy service metadata missing. Create a full deployment bundle.\\n' >&2; exit 1; }\n case \" $selected \" in *\" $current_proxy \"*) ;; *) selected=\"$selected $current_proxy\"; proxy_update=true;; esac\n fi\nfi\nmkdir -p \"$release\"\n# 镜像直接从本次解包目录导入;发布记录只保存运行配置与恢复证据。\nfor entry in \"$source_dir\"/* \"$source_dir\"/.[!.]*; do\n test -e \"$entry\" || continue\n test \"$entry\" != \"$source_dir/images\" || continue\n cp -R \"$entry\" \"$release/\"\ndone\n# Nginx 以非 root 用户运行;只开放不含凭据的代理配置读取权限。\nif [ -f \"$release/web.conf\" ]; then chmod 644 \"$release/web.conf\"; fi\nfor https_script in https-start.sh renew-https.sh; do\n if [ -f \"$release/$https_script\" ]; then chmod 444 \"$release/$https_script\"; fi\ndone\n# 策略不是凭据,发布目录保持700;只读挂载允许镜像中的非root应用读取。\nif [ -f \"$release/request-access.yml\" ]; then chmod 444 \"$release/request-access.yml\"; fi\n: > \"$release/compose-files\"\nif [ \"$partial\" = true ]; then\n cp \"$root/releases/$previous/compose-files\" \"$release/compose-files\"\n # 旧版本的生成文件混有镜像原生变量;每项单行,只继承框架连接配置。\n awk '/^HAI_[A-Z0-9_]+=/ { print }' \"$root/releases/$previous/middleware.env\" > \"$release/middleware.env\"\n for service in $selected; do\n grep -qx \"$service\" \"$root/releases/$previous/services\" || { printf 'Service %s has no installed baseline. Use a full deployment.\\n' \"$service\" >&2; exit 1; }\n done\nfi\nstep credentials 'Resolving server-managed middleware credentials'\nsh \"$release/resolve-managed-secrets.sh\" \"$root\" \"$release\" \"$runtime\"\nif [ -f \"$release/runtime-env.mjs\" ]; then\n # 上级目录保护宿主秘密;只读文件挂载允许非 root 应用读取,宿主所有者仍可修改配置。\n chmod 700 \"$root\" \"$release\"\n chmod 644 \"$release/.env.runtime\" \"$release/middleware.env\"\n chmod 444 \"$release/runtime-env.mjs\"\nfi\n# 在任何可能启动服务(包括增量恢复旧拓扑)之前定稿,失败回滚不删除卷的引擎身份。\nsh \"$release/resolve-backend-state.sh\" \"$root\" \"$release\" \"$runtime\" \"$previous\" commit\nprintf '%s\\n' \"$release/compose-entry.json\" >> \"$release/compose-files\"\nif [ \"$proxy_update\" = true ]; then\n printf '%s\\n' \"$release/proxy-entry.json\" >> \"$release/compose-files\"\nfi\ncompose config >/dev/null\ncompose config --services > \"$release/services\"\n# 增量包依赖已安装的完整基线;先恢复 down/stop 后的服务,使用旧配置和本地镜像,不重建运行中的容器。\nif [ \"$partial\" = true ]; then\n recover=false\n while IFS= read -r service; do\n case \" $selected \" in *\" $service \"*) continue;; esac\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -q)\n if [ -z \"$containers\" ]; then recover=true; fi\n done < \"$release/services\"\n if [ \"$recover\" = true ]; then\n step recover 'Starting stopped services from the installed baseline'\n restore=$previous\n sh \"$release/resolve-backend-state.sh\" \"$root\" \"$release\" \"$runtime\" \"$previous\" recover\n start_services $(cat \"$root/releases/$previous/services\")\n restore=''\n fi\nfi\n: > \"$release/rollback-images\"\nif [ -n \"$previous\" ]; then\n for service in $selected; do\n containers=$(compose_container_ids \"$runtime\" \"$project\" \"$service\" -aq)\n for container in $containers; do\n \"$runtime\" inspect --format '{{.Image}} {{.Config.Image}}' \"$container\" >> \"$release/rollback-images\"\n done\n done\nfi\nstep images 'Loading packaged images (no registry access)'\nwhile IFS=' ' read -r archive reference; do\n test -n \"$archive\" || continue\n images_changed=true\n \"$runtime\" load -i \"$source_dir/images/$archive\"\n \"$runtime\" image inspect \"$reference\" >/dev/null\n architecture=$(\"$runtime\" image inspect --format '{{.Architecture}}' \"$reference\")\n host_arch=$(uname -m)\n case \"$host_arch:$architecture\" in x86_64:amd64|aarch64:arm64) ;; *) printf 'Image architecture %s does not match server %s\\n' \"$architecture\" \"$host_arch\" >&2; exit 1;; esac\ndone < \"$release/image-list\"\nif [ -f \"$release/prepare-https.sh\" ]; then\n sh \"$release/prepare-https.sh\" \"$root\" \"$release\" \"$runtime\" prepare \"$partial\"\nfi\nstep dependencies 'Checking dependencies of selected services'\nif [ \"$partial\" = true ]; then cat \"$release/services\" >> \"$release/dependencies\"; fi\nwhile IFS= read -r dependency; do\n test -n \"$dependency\" || continue\n case \" $selected \" in *\" $dependency \"*) continue;; esac\n wait_services \"$dependency\"\ndone < \"$release/dependencies\"\nstep start 'Updating selected services'\nchanged=true\nremove_selected $selected\nstart_services $selected\nif [ -f \"$release/prepare-https.sh\" ] && [ \"$partial\" = false ]; then\n step https 'Issuing or installing HTTPS certificate'\n tls_proxy=$(read_proxy_service \"$release\")\n wait_services \"$tls_proxy\"\n sh \"$release/prepare-https.sh\" \"$root\" \"$release\" \"$runtime\" issue \"$partial\"\n compose exec -T \"$tls_proxy\" nginx -t\n compose exec -T \"$tls_proxy\" nginx -s reload\nfi\nstart_renewal $selected\nreload_retained_proxy \"$release\"\nstep health 'Checking HTTP access'\nwait_http \"$release\" @@PORT@@ @@HEALTH@@\nstep complete 'Deployment passed all checks'\nprintf '%s\\n' \"$id\" > \"$root/current.next\"\nmv \"$root/current.next\" \"$root/current\"\ncase \" $selected \" in *' @@PRIMARY@@ '*)\n if grep -q '^HAI_ADMIN_DEFAULT_PASSWORD=' \"$release/.env.runtime\"; then\n printf '[INFO] Initial administrator password source: %s/.env.runtime (HAI_ADMIN_DEFAULT_PASSWORD). Existing users keep their passwords.\\n' \"$release\"\n fi\n ;;\nesac\nprintf '[PASS] %s\\n' \"$id\"\n`.replace(/@@([A-Z]+)@@/g, (_match, name: string) => values[name]!)\n}\n\n/**\n * 生成无 Node/pnpm 依赖的上传脚本;换电脑时可覆盖 SSH 私钥路径。\n * Windows PowerShell 5 会丢弃原生参数内部引号,须直接按 Win32 规则构造命令行。\n * 两个入口执行时读取旁边的 deploy-target.json;apply 阶段 SSH 失败仍须核对远端状态。\n * @returns Linux shell、Windows PowerShell 上传入口及 POSIX awk 配置读取器文本。\n * @example 模块内部上下文\n * ```ts\n * const scripts = createUploadScripts()\n * const files = { 'deploy.sh': scripts.sh, 'deploy.ps1': scripts.ps1, 'read-target.awk': scripts.reader }\n * // 将三个文件与 deploy-target.json 放在操作目录;生成文本不代表已部署。\n * ```\n */\nexport function createUploadScripts(): { sh: string, ps1: string, reader: string } {\n const sh = String.raw`#!/bin/sh\n# 操作机上传入口:整个交付目录可直接复制;tar、deploy-target.json 与本脚本须放在同一目录。\n# 先修改 deploy-target.json 的服务器、用户、密钥路径;需要 sh、awk 及 OpenSSH 的 ssh/scp。\n# 密码缺失时从终端隐藏输入,需要 stty;输入仅用于本次部署。\n# 执行:sh deploy.sh [主机 [端口 [用户]]];可用 HAI_DEPLOY_IDENTITY_FILE 覆盖当前电脑的私钥。\n# tar 内 manifest.json 的 partial/selectedServices 说明本次模式;服务器会核验增量基线,上传后自动部署并检查 HTTP。\nset -eu\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\ncd \"$source_dir\"\ncommand -v awk >/dev/null || { printf 'Install POSIX awk to read deploy-target.json.\\n' >&2; exit 1; }\nread_target() {\n LC_ALL=C awk -v field=\"$1\" -v expected=\"$2\" -v fallback=\"$3\" -f \"$source_dir/read-target.awk\" \"$source_dir/deploy-target.json\"\n}\nhost=$(read_target host string SERVER_HOST)\nuser=$(read_target username string deploy)\nport=$(read_target port number 22)\nremote=$(read_target directory string '')\nbundle=$(read_target bundle string '')\nidentity=$(read_target identityFile string '')\nknown_hosts=$(read_target knownHostsFile string '')\nstrict=$(read_target strictHostKeyChecking boolean true)\ntimeout=$(read_target connectTimeoutSeconds number 10)\nauth=$(read_target auth string key)\npassword_env=$(read_target passwordEnv string HAI_DEPLOY_PROVIDER_SSH_PASSWORD)\ntest -z \"$(read_target password string '')\" || { printf 'Password values are forbidden in deploy-target.json. Use passwordEnv.\\n' >&2; exit 1; }\nif [ \"$#\" -ge 1 ]; then host=$1; fi\nif [ \"$#\" -ge 2 ]; then port=$2; fi\nif [ \"$#\" -ge 3 ]; then user=$3; fi\nif value=$(printenv HAI_DEPLOY_IDENTITY_FILE) && [ -n \"$value\" ]; then identity=$value; fi\nif value=$(printenv HAI_DEPLOY_KNOWN_HOSTS_FILE) && [ -n \"$value\" ]; then known_hosts=$value; fi\ninvalid_target() { printf 'Invalid deployment target. Edit deploy-target.json before running this script.\\n' >&2; exit 1; }\ntest \"$host\" != SERVER_HOST || { printf 'Specify the server: sh deploy.sh SERVER [PORT] [USER].\\n' >&2; exit 1; }\ncase \"$host\" in ''|*[!a-zA-Z0-9.:-]*|[!a-zA-Z0-9]*) invalid_target;; esac\ncase \"$user\" in ''|*[!a-zA-Z0-9_-]*|[!a-zA-Z_]*) invalid_target;; esac\ncase \"$port\" in ''|*[!0-9]*|???????????*) invalid_target;; esac\ntest \"$port\" -ge 1 && test \"$port\" -le 65535 || invalid_target\ncase \"$timeout\" in ''|*[!0-9]*|???????????*) invalid_target;; esac\ntest \"$timeout\" -ge 1 && test \"$timeout\" -le 2147483647 || invalid_target\ncase \"$remote\" in /*) ;; *) invalid_target;; esac\ncase \"$remote\" in *[!a-zA-Z0-9/_.\\ -]*|*/../*|*/..|/..) invalid_target;; esac\ncase \"$bundle\" in *.tar|*.tar.gz) ;; *) invalid_target;; esac\ncase \"$bundle\" in ''|*[!a-zA-Z0-9_.+-]*) invalid_target;; esac\ncase \"$strict\" in true) strict=accept-new;; false) strict=no;; *) invalid_target;; esac\ntest -f \"./$bundle\" || { printf 'Bundle missing: %s\\n' \"$bundle\" >&2; exit 1; }\nfor tool in ssh scp; do command -v \"$tool\" >/dev/null || { printf 'Install OpenSSH (%s).\\n' \"$tool\" >&2; exit 1; }; done\ntemporary=''\ntemporary_root=''\nupload=''\nmonitor=''\ntty_state=''\ncleanup() {\n # 中断隐藏输入时也恢复调用者的终端回显。\n if [ -n \"$tty_state\" ]; then\n (stty \"$tty_state\" </dev/tty; printf '\\n' >/dev/tty) 2>/dev/null || :\n fi\n if [ -n \"$monitor\" ]; then kill \"$monitor\" 2>/dev/null || :; wait \"$monitor\" 2>/dev/null || :; fi\n if [ -n \"$upload\" ]; then kill \"$upload\" 2>/dev/null || :; wait \"$upload\" 2>/dev/null || :; fi\n if [ -n \"$temporary\" ]; then\n case \"$temporary\" in \"$temporary_root\"/hai-ssh-askpass.*) test ! -L \"$temporary\" && rm -rf -- \"$temporary\";; *) return 1;; esac\n fi\n}\ntrap cleanup EXIT\ntrap 'exit 130' HUP INT TERM\ncase \"$auth\" in key|password) ;; *) invalid_target;; esac\ncase \"$password_env\" in HAI_DEPLOY_[A-Z0-9_]*) ;; *) invalid_target;; esac\ncase \"$password_env\" in *[!A-Z0-9_]*) invalid_target;; esac\nset -- -o \"StrictHostKeyChecking=$strict\" -o \"ConnectTimeout=$timeout\"\nif [ \"$auth\" = password ]; then\n for tool in mktemp mkfifo od; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\n # 后缀哨兵保留末尾换行,以便拒绝 readpass 无法安全传递的 CR/LF。\n password=''\n if password=$(printenv \"$password_env\" && printf '.'); then\n password=@@PASSWORD_TRIM@@\n password=@@PASSWORD_NEWLINE@@\n fi\n if [ -z \"$password\" ]; then\n if ! command -v stty >/dev/null || ! ( : </dev/tty >/dev/tty ) 2>/dev/null; then\n printf '%s: %s\\n' \"$password_env\" @@PASSWORD_UNAVAILABLE@@ >&2\n exit 1\n fi\n tty_state=$(stty -g </dev/tty)\n stty -echo </dev/tty\n printf '%s (%s): ' @@PASSWORD_PROMPT@@ \"$password_env\" >/dev/tty\n if IFS= read -r password </dev/tty; then input_code=0; else input_code=$?; fi\n stty \"$tty_state\" </dev/tty\n tty_state=''\n printf '\\n' >/dev/tty\n if [ \"$input_code\" -ne 0 ]; then printf '%s\\n' @@PASSWORD_CANCELLED@@ >&2; exit 1; fi\n fi\n export HAI_DEPLOY_ASKPASS_PASSWORD=\"$password\"\n if ! LC_ALL=C awk 'BEGIN {p=ENVIRON[\"HAI_DEPLOY_ASKPASS_PASSWORD\"]; exit (length(p) == 0 || length(p) > 1023 || p ~ /[\\r\\n]/) ? 1 : 0}'; then printf '%s: %s\\n' \"$password_env\" @@PASSWORD_INVALID@@ >&2; exit 1; fi\n umask 077\n temporary_root=$(CDPATH= cd -- \"@@TEMP_ROOT@@\" && pwd -P)\n temporary=$(mktemp -d \"$temporary_root/hai-ssh-askpass.XXXXXXXX\")\n cat > \"$temporary/askpass.sh\" <<'HAI_ASKPASS'\n#!/bin/sh\ntest \"@@ASKPASS_PROMPT@@\" != confirm || exit 1\ntest -n \"$HAI_DEPLOY_ASKPASS_PASSWORD\" || exit 1\nprintf '%s\\n' \"$HAI_DEPLOY_ASKPASS_PASSWORD\"\nHAI_ASKPASS\n chmod 700 \"$temporary/askpass.sh\"\n export SSH_ASKPASS=\"$temporary/askpass.sh\" SSH_ASKPASS_REQUIRE=force SSH_ASKPASS_PROMPT='' DISPLAY=hai-deploy:0\n set -- \"$@\" -o BatchMode=no -o PreferredAuthentications=password -o PasswordAuthentication=yes -o PubkeyAuthentication=no -o NumberOfPasswordPrompts=1\nelse\n set -- \"$@\" -o BatchMode=yes\n if [ -n \"$identity\" ]; then set -- \"$@\" -i \"$identity\" -o IdentitiesOnly=yes; fi\nfi\n# 固定字节流过滤器最多保留一个密码长度,不把值交给 argv、正则或磁盘。\nrun_native() {\n if [ \"$auth\" = key ]; then \"$@\"; return; fi\n # 每次调用独立管道,允许上传与进度查询并行且保持密码脱敏。\n output=$(mktemp \"$temporary/output.XXXXXXXX\") || return 1\n rm -f \"$output\"\n mkfifo \"$output\" || return 1\n (od -An -v -tu1 \"$output\" | LC_ALL=C awk '\n BEGIN {secret=ENVIRON[\"HAI_DEPLOY_ASKPASS_PASSWORD\"]; n=length(secret); pending=\"\"}\n {for(i=1;i<=NF;i++) {pending=pending sprintf(\"%c\",$i); while(length(pending)>=n) {\n if(substr(pending,1,n)==secret) {printf \"***\"; pending=substr(pending,n+1)}\n else {printf \"%s\",substr(pending,1,1); pending=substr(pending,2)}\n }}}\n END {printf \"%s\",pending}') &\n filter=$!\n if \"$@\" > \"$output\" 2>&1; then code=0; else code=$?; fi\n if ! wait \"$filter\"; then printf 'Cannot filter SSH output.\\n' >&2; return 1; fi\n rm -f \"$output\"\n return \"$code\"\n}\nif [ -n \"$known_hosts\" ]; then\n known_hosts=$(printf '%s' \"$known_hosts\" | sed 's/[\\\\\"]/\\\\&/g')\n set -- \"$@\" -o \"UserKnownHostsFile=\\\"$known_hosts\\\"\"\nfi\nprintf '[1/3] Connecting to %s\\n' \"$host\"\nrun_native ssh \"$@\" -p \"$port\" \"$user@$host\" \"mkdir -p '$remote/incoming' && chmod 700 '$remote' '$remote/incoming'\"\nprintf '[2/3] Uploading %s\\n' \"$bundle\"\nscp_host=$host\ncase \"$host\" in *:*) scp_host=\"[$host]\";; esac\ntotal=$(wc -c < \"./$bundle\" | tr -d '[:space:]')\nprintf '[UPLOAD] 0%% (0/%s bytes)\\n' \"$total\"\nrun_native scp \"$@\" -P \"$port\" \"./$bundle\" \"$user@$scp_host:$remote/incoming/$bundle\" &\nupload=$!\n(\n pause=''\n trap 'if [ -n \"$pause\" ]; then kill \"$pause\" 2>/dev/null || :; wait \"$pause\" 2>/dev/null || :; fi; exit 0' HUP INT TERM\n while kill -0 \"$upload\" 2>/dev/null; do\n sleep 2 &\n pause=$!\n wait \"$pause\" || exit 1\n pause=''\n kill -0 \"$upload\" 2>/dev/null || break\n received=$(run_native ssh \"$@\" -p \"$port\" \"$user@$host\" \"wc -c < '$remote/incoming/$bundle'\" 2>/dev/null) || continue\n received=$(printf '%s' \"$received\" | tr -d '[:space:]')\n case \"$received\" in ''|*[!0-9]*) continue;; esac\n LC_ALL=C awk -v done=\"$received\" -v total=\"$total\" 'BEGIN {percent=total>0 ? done*100/total : 0; if(percent>99) percent=99; printf \"[UPLOAD] %.0f%% (%s/%s bytes)\\n\",percent,done,total}'\n done\n) &\nmonitor=$!\nif wait \"$upload\"; then upload_code=0; else upload_code=$?; fi\nupload=''\nkill \"$monitor\" 2>/dev/null || :\nwait \"$monitor\" 2>/dev/null || :\nmonitor=''\nif [ \"$upload_code\" -ne 0 ]; then printf '[FAIL] Upload failed (exit %s). Check SSH output above.\\n' \"$upload_code\" >&2; exit \"$upload_code\"; fi\nprintf '[UPLOAD] 100%% (%s/%s bytes)\\n' \"$total\" \"$total\"\nprintf '[3/3] Applying package and checking HTTP access\\n'\nif run_native ssh \"$@\" -p \"$port\" \"$user@$host\" \"cd '$remote/incoming' && mkdir -p '$bundle.contents' && tar -xf '$bundle' -C '$bundle.contents' && sh '$bundle.contents/apply.sh' '$remote' && { rm -rf -- '$bundle.contents' && rm -f -- '$bundle' || printf '[WARN] Deployment passed; incoming archive cleanup failed\\\\n' >&2; }\"; then\n :\nelse\n code=$?\n if [ \"$code\" -lt 128 ]; then\n printf '[FAIL] Remote deployment failed (exit %s). Inspect %s/result-<deploymentId>.json (ID in README.txt) and startup diagnostics.\\n' \"$code\" \"$remote\" >&2\n else\n printf '[UNKNOWN] Remote execution may continue. Inspect %s/result-<deploymentId>.json (ID in README.txt), current and containers before retrying.\\n' \"$remote\" >&2\n fi\n exit \"$code\"\nfi\n`.replace('@@PASSWORD_TRIM@@', '$' + '{password%.}').replace('@@PASSWORD_NEWLINE@@', '$' + '{password%?}').replace('@@TEMP_ROOT@@', '$' + '{TMPDIR:-/tmp}').replace('@@ASKPASS_PROMPT@@', '$' + '{SSH_ASKPASS_PROMPT:-}')\n const ps1 = String.raw`<#\n操作机上传入口:复制整个交付目录后,先修改同目录 deploy-target.json 的服务器、用户和密钥路径。\n需要 Windows PowerShell 5+/PowerShell 及 OpenSSH 的 ssh/scp;tar 必须与本脚本放在同一目录。\n执行:powershell -File .\\deploy.ps1 [-IdentityFile 当前电脑的私钥路径]。\ntar 内 manifest.json 的 partial/selectedServices 标明全量或增量;服务器会检查基线,上传后自动部署并核验 HTTP。\nSSH 中断时先核对远端结果文件和容器状态,再决定是否重试。\n#>\nparam([string]$IdentityFile = $env:HAI_DEPLOY_IDENTITY_FILE)\n$ErrorActionPreference = 'Stop'\n# Windows PowerShell 5 的重定向错误流默认沿用本机代码页;统一 UTF-8,保留多语言提示。\n[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)\n$OutputEncoding = [Console]::OutputEncoding\n$windowsRuntime = [Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT\n$previousSystemRoot = [Environment]::GetEnvironmentVariable('SystemRoot', 'Process')\ntry {\nif ($windowsRuntime) {\n $windowsDirectory = [Environment]::GetFolderPath('Windows')\n if ([string]::IsNullOrEmpty($windowsDirectory)) { throw 'Cannot locate the Windows system directory.' }\n $env:SystemRoot = $windowsDirectory\n}\nSet-Location -LiteralPath $PSScriptRoot\n$target = Get-Content -LiteralPath (Join-Path $PSScriptRoot 'deploy-target.json') -Raw -Encoding UTF8 | ConvertFrom-Json\nif ($target.host -eq 'SERVER_HOST') { throw 'Set the server host in deploy-target.json.' }\nif ($target.host -isnot [string] -or $target.host -notmatch '^[a-zA-Z0-9][a-zA-Z0-9.:-]*$' -or $target.username -isnot [string] -or $target.username -notmatch '^[a-zA-Z_][a-zA-Z0-9_-]*$' -or $target.directory -isnot [string] -or $target.directory -notmatch '^/[a-zA-Z0-9/_. -]*$' -or $target.directory -match '(^|/)\\.\\.(/|$)' -or $target.bundle -isnot [string] -or $target.bundle -notmatch '^[a-zA-Z0-9_.+-]+\\.tar(\\.gz)?$') { throw 'Invalid deployment target.' }\n$port = if ($null -eq $target.port) { 22 } else { $target.port }\n$timeout = if ($null -eq $target.connectTimeoutSeconds) { 10 } else { $target.connectTimeoutSeconds }\nif ($port -is [string] -or [string]$port -notmatch '^[0-9]+$' -or $port -lt 1 -or $port -gt 65535 -or $timeout -is [string] -or [string]$timeout -notmatch '^[0-9]+$' -or $timeout -lt 1 -or $timeout -gt 2147483647) { throw 'Invalid deployment port or timeout.' }\nif ($null -ne $target.strictHostKeyChecking -and $target.strictHostKeyChecking -isnot [bool]) { throw 'Invalid host key policy.' }\nif (($null -ne $target.identityFile -and $target.identityFile -isnot [string]) -or ($null -ne $target.knownHostsFile -and $target.knownHostsFile -isnot [string])) { throw 'Invalid SSH file path.' }\n$strict = if ($target.strictHostKeyChecking -eq $false) { 'no' } else { 'accept-new' }\n$auth = if ($null -eq $target.auth) { 'key' } else { $target.auth }\n$passwordEnv = if ($null -eq $target.passwordEnv) { 'HAI_DEPLOY_PROVIDER_SSH_PASSWORD' } else { $target.passwordEnv }\nif ($auth -isnot [string] -or $auth -notin @('key', 'password') -or $passwordEnv -isnot [string] -or $passwordEnv -cnotmatch '^HAI_DEPLOY_[A-Z0-9_]+$' -or $null -ne $target.password) { throw 'Invalid SSH authentication configuration. Store only passwordEnv in the target; passwords are read locally or prompted.' }\n$options = @('-o', \"StrictHostKeyChecking=$strict\", '-o', \"ConnectTimeout=$timeout\")\nif (-not $IdentityFile) { $IdentityFile = $target.identityFile }\nif ($auth -eq 'password') {\n $options += @('-o', 'BatchMode=no', '-o', 'PreferredAuthentications=password', '-o', 'PasswordAuthentication=yes', '-o', 'PubkeyAuthentication=no', '-o', 'NumberOfPasswordPrompts=1')\n} else {\n $options += @('-o', 'BatchMode=yes')\n if ($IdentityFile) { $options += @('-i', $IdentityFile, '-o', 'IdentitiesOnly=yes') }\n}\n$knownHosts = if ($env:HAI_DEPLOY_KNOWN_HOSTS_FILE) { $env:HAI_DEPLOY_KNOWN_HOSTS_FILE } else { $target.knownHostsFile }\nif ($knownHosts) {\n $knownHosts = $knownHosts.Replace('\\', '\\\\').Replace('\"', '\\\"')\n $options += @('-o', ('UserKnownHostsFile=\"' + $knownHosts + '\"'))\n}\n$destination = \"$($target.username)@$($target.host)\"\n$scpDestination = if ($target.host.Contains(':')) { \"$($target.username)@[$($target.host)]\" } else { $destination }\n$remote = $target.directory\n$bundle = $target.bundle\nif (-not (Test-Path -LiteralPath \"./$bundle\" -PathType Leaf)) { throw \"Bundle missing: $bundle\" }\nfunction ConvertTo-NativeArgument([string]$Value) {\n if ($Value.Length -gt 0 -and $Value -notmatch '[\\s\"]') { return $Value }\n $escaped = [regex]::Replace($Value, '(\\\\*)\"', '$1$1\\\"')\n $escaped = [regex]::Replace($escaped, '(\\\\+)$', '$1$1')\n return '\"' + $escaped + '\"'\n}\nfunction Invoke-Step([string]$Name, [string]$Command, [string[]]$Arguments) {\n Write-Host \"[$Name]\"\n $nativeCommand = Get-Command $Command -ErrorAction Stop\n if ($auth -eq 'password' -and $nativeCommand.CommandType -eq 'Application') {\n $Arguments = @('--run', $nativeCommand.Source) + $Arguments\n $nativeCommand = Get-Command $env:SSH_ASKPASS -ErrorAction Stop\n }\n if ($nativeCommand.CommandType -eq 'Application') {\n $start = New-Object System.Diagnostics.ProcessStartInfo\n $start.FileName = $nativeCommand.Source\n $start.WorkingDirectory = (Get-Location).ProviderPath\n $start.UseShellExecute = $false\n $start.CreateNoWindow = $true\n $start.RedirectStandardOutput = $true\n $start.RedirectStandardError = $true\n $start.StandardOutputEncoding = New-Object System.Text.UTF8Encoding($false)\n $start.StandardErrorEncoding = New-Object System.Text.UTF8Encoding($false)\n $start.Arguments = ($Arguments | ForEach-Object { ConvertTo-NativeArgument $_ }) -join ' '\n $child = [System.Diagnostics.Process]::Start($start)\n # 持续转发 SSH/部署诊断;密码模式的输出已由独立 helper 脱敏。\n $streams = @(\n @{ Reader = $child.StandardOutput; Pending = $child.StandardOutput.ReadLineAsync(); Writer = [Console]::Out },\n @{ Reader = $child.StandardError; Pending = $child.StandardError.ReadLineAsync(); Writer = [Console]::Error }\n )\n $clock = [Diagnostics.Stopwatch]::StartNew()\n $nextProgress = 2000\n try {\n while (-not $child.HasExited -or $null -ne $streams[0].Pending -or $null -ne $streams[1].Pending) {\n foreach ($stream in $streams) {\n while ($null -ne $stream.Pending -and $stream.Pending.IsCompleted) {\n $line = $stream.Pending.GetAwaiter().GetResult()\n if ($null -eq $line) { $stream.Pending = $null }\n else { $stream.Writer.WriteLine($line); $stream.Pending = $stream.Reader.ReadLineAsync() }\n }\n }\n if ($Command -eq 'scp' -and -not $child.HasExited -and $clock.ElapsedMilliseconds -ge $nextProgress) {\n $nextProgress = $clock.ElapsedMilliseconds + 2000\n $query = $null\n try {\n $probe = New-Object System.Diagnostics.ProcessStartInfo\n $probe.FileName = (Get-Command ssh -ErrorAction Stop).Source\n $probeArgs = $options + @('-p', [string]$port, $destination, \"wc -c < '$remote/incoming/$bundle'\")\n if ($auth -eq 'password') { $probeArgs = @('--run', $probe.FileName) + $probeArgs; $probe.FileName = $env:SSH_ASKPASS }\n $probe.UseShellExecute = $false; $probe.CreateNoWindow = $true\n $probe.RedirectStandardOutput = $true; $probe.RedirectStandardError = $true\n $probe.Arguments = ($probeArgs | ForEach-Object { ConvertTo-NativeArgument $_ }) -join ' '\n $query = [System.Diagnostics.Process]::Start($probe)\n try {\n $stdout = $query.StandardOutput.ReadToEndAsync()\n $stderr = $query.StandardError.ReadToEndAsync()\n if (-not $query.WaitForExit(5000)) { $query.Kill(); $query.WaitForExit() }\n $received = $stdout.Result.Trim()\n if ($query.ExitCode -eq 0 -and $received -match '^[0-9]+$') {\n $percent = if ($uploadBytes -gt 0) { [Math]::Min(99, [Math]::Floor([double]$received * 100 / $uploadBytes)) } else { 0 }\n Write-Host \"[UPLOAD] $percent% ($received/$uploadBytes bytes)\"\n Write-Progress -Activity \"Uploading $bundle\" -Status \"$received/$uploadBytes bytes\" -PercentComplete $percent\n }\n } finally { if ($null -ne $query) { $query.Dispose() } }\n } catch { [Console]::Error.WriteLine('[UPLOAD] Progress query unavailable; transfer continues.') }\n }\n Start-Sleep -Milliseconds 50\n }\n $code = $child.ExitCode\n } finally { $child.Dispose(); if ($Command -eq 'scp') { Write-Progress -Activity \"Uploading $bundle\" -Completed } }\n } else {\n $invokeCommand = if ($nativeCommand.CommandType -eq 'Application') { $nativeCommand.Source } else { $Command }\n & $invokeCommand @Arguments\n $code = $LASTEXITCODE\n }\n $global:LASTEXITCODE = $code\n if ($code -ne 0) { throw \"$Name failed (exit $code).\" }\n}\n$applying = $false\n$temporary = $null\n$temporaryRoot = [System.IO.Path]::GetFullPath([System.IO.Path]::GetTempPath()).TrimEnd([System.IO.Path]::DirectorySeparatorChar)\n$savedEnvironment = @{}\ntry {\n foreach ($tool in @('ssh', 'scp')) { Get-Command $tool -ErrorAction Stop | Out-Null }\n if ($auth -eq 'password') {\n $password = [Environment]::GetEnvironmentVariable($passwordEnv, 'Process')\n if ($null -eq $password -and $windowsRuntime) { $password = [Environment]::GetEnvironmentVariable($passwordEnv, 'User') }\n if ([string]::IsNullOrEmpty($password)) {\n if ($Host.Name -eq 'ConsoleHost' -and [Console]::IsInputRedirected) { throw ($passwordEnv + ': ' + @@PASSWORD_UNAVAILABLE@@) }\n $secure = $null\n $pointer = [IntPtr]::Zero\n try {\n $secure = Read-Host -Prompt (@@PASSWORD_PROMPT@@ + ' (' + $passwordEnv + ')') -AsSecureString\n $pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure)\n $password = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer)\n } catch { throw ($passwordEnv + ': ' + @@PASSWORD_UNAVAILABLE@@) }\n finally {\n if ($pointer -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer) }\n if ($null -ne $secure) { $secure.Dispose() }\n }\n }\n if ([string]::IsNullOrEmpty($password) -or $password.IndexOfAny([char[]]@([char]0, [char]10, [char]13)) -ge 0 -or [Text.Encoding]::UTF8.GetByteCount($password) -gt 1023) { throw ($passwordEnv + ': ' + @@PASSWORD_INVALID@@) }\n foreach ($name in @('SSH_ASKPASS', 'SSH_ASKPASS_REQUIRE', 'SSH_ASKPASS_PROMPT', 'DISPLAY', 'HAI_DEPLOY_ASKPASS_PASSWORD', 'HAI_DEPLOY_ASKPASS_SOURCE', 'HAI_DEPLOY_ASKPASS_OUTPUT')) { $savedEnvironment[$name] = [Environment]::GetEnvironmentVariable($name, 'Process') }\n $temporary = Join-Path $temporaryRoot ('hai-ssh-askpass-' + [Guid]::NewGuid().ToString('N'))\n [System.IO.Directory]::CreateDirectory($temporary) | Out-Null\n $source = Join-Path $temporary 'askpass.cs'\n $helper = Join-Path $temporary 'askpass.exe'\n [System.IO.File]::WriteAllText($source, @'\n@@WINDOWS_ASKPASS@@\n'@, (New-Object System.Text.UTF8Encoding($false)))\n $env:HAI_DEPLOY_ASKPASS_SOURCE = $source\n $env:HAI_DEPLOY_ASKPASS_OUTPUT = $helper\n # 编译进程不继承专用密码;固定源码及命令均不包含凭据。\n $env:HAI_DEPLOY_ASKPASS_PASSWORD = ''\n if (-not $windowsRuntime) { throw 'Use sh deploy.sh for password authentication on POSIX systems.' }\n $compiler = Join-Path $windowsDirectory 'System32/WindowsPowerShell/v1.0/powershell.exe'\n $compileScript = '$ErrorActionPreference=\"Stop\"; Add-Type -Language CSharp -TypeDefinition ([System.IO.File]::ReadAllText($env:HAI_DEPLOY_ASKPASS_SOURCE, [System.Text.Encoding]::UTF8)) -OutputType ConsoleApplication -OutputAssembly $env:HAI_DEPLOY_ASKPASS_OUTPUT'\n & $compiler -NoProfile -NonInteractive -EncodedCommand ([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($compileScript))) 2>&1 | Out-Null\n if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $helper -PathType Leaf)) { throw 'Cannot prepare the SSH password helper.' }\n $env:SSH_ASKPASS = $helper\n $env:SSH_ASKPASS_REQUIRE = 'force'\n $env:SSH_ASKPASS_PROMPT = ''\n $env:DISPLAY = 'hai-deploy:0'\n $env:HAI_DEPLOY_ASKPASS_PASSWORD = $password\n }\n Invoke-Step '1/3 Connect' 'ssh' ($options + @('-p', [string]$port, $destination, \"mkdir -p '$remote/incoming' && chmod 700 '$remote' '$remote/incoming'\"))\n $uploadBytes = (Get-Item -LiteralPath \"./$bundle\").Length\n Write-Host \"[UPLOAD] 0% (0/$uploadBytes bytes)\"\n Invoke-Step '2/3 Upload' 'scp' ($options + @('-P', [string]$port, \"./$bundle\", \"$($scpDestination):$remote/incoming/$bundle\"))\n Write-Host \"[UPLOAD] 100% ($uploadBytes/$uploadBytes bytes)\"\n $applying = $true\n Invoke-Step '3/3 Apply and verify HTTP' 'ssh' ($options + @('-p', [string]$port, $destination, \"cd '$remote/incoming' && mkdir -p '$bundle.contents' && tar -xf '$bundle' -C '$bundle.contents' && sh '$bundle.contents/apply.sh' '$remote' && { rm -rf -- '$bundle.contents' && rm -f -- '$bundle' || printf '[WARN] Deployment passed; incoming archive cleanup failed\\\\n' >&2; }\"))\n} catch {\n if ($applying) {\n if ($LASTEXITCODE -gt 0 -and $LASTEXITCODE -lt 128) { [Console]::Error.WriteLine(\"[FAIL] Remote deployment failed (exit $LASTEXITCODE). Inspect $remote/result-<deploymentId>.json (ID in README.txt) and startup diagnostics.\") }\n else { [Console]::Error.WriteLine(\"[UNKNOWN] Remote execution may continue. Inspect $remote/result-<deploymentId>.json (ID in README.txt), current and containers before retrying.\") }\n }\n throw\n} finally {\n foreach ($name in $savedEnvironment.Keys) { [Environment]::SetEnvironmentVariable($name, $savedEnvironment[$name], 'Process') }\n if ($null -ne $temporary -and (Test-Path -LiteralPath $temporary)) {\n $item = Get-Item -LiteralPath $temporary -Force\n if ([System.IO.Path]::GetDirectoryName([System.IO.Path]::GetFullPath($temporary)) -ne $temporaryRoot -or $item.Name -notlike 'hai-ssh-askpass-*' -or ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) { throw 'Refusing to clean an unexpected SSH helper directory.' }\n Remove-Item -LiteralPath $temporary -Recurse -Force\n }\n}\n} finally {\n if ($windowsRuntime) {\n if ($null -eq $previousSystemRoot) { Remove-Item -LiteralPath Env:SystemRoot -ErrorAction SilentlyContinue }\n else { [Environment]::SetEnvironmentVariable('SystemRoot', $previousSystemRoot, 'Process') }\n }\n}\n`.replace('@@WINDOWS_ASKPASS@@', windowsAskpassSource)\n // Windows PowerShell 5 将无 BOM 的 UTF-8 视为 ANSI;中文注释也可能改变脚本的实际解析结果。\n const messages: Record<string, string> = {\n PROMPT: deployM('deploy_uploadPasswordPrompt'),\n UNAVAILABLE: deployM('deploy_uploadPasswordUnavailable'),\n CANCELLED: deployM('deploy_uploadPasswordCancelled'),\n INVALID: deployM('deploy_uploadPasswordInvalid'),\n }\n const pattern = /@@PASSWORD_(PROMPT|UNAVAILABLE|CANCELLED|INVALID)@@/g\n return {\n sh: sh.replace(pattern, (_match, name: string) => shellArgument(messages[name]!)),\n ps1: `\\uFEFF${ps1.replace(pattern, (_match, name: string) => `'${messages[name]!.replaceAll('\\'', '\\'\\'')}'`)}`,\n reader: createTargetReader(),\n }\n}\n\n/**\n * 生成服务器本地入口,自动解包后调用同一 apply 流程。\n * @param options - 同目录 tar 名称和默认服务器部署目录;都由已校验的部署配置生成。\n * @param options.bundle - 不含目录的 tar 文件名。\n * @param options.directory - 服务器部署目录,执行时可用第一个参数覆盖。\n * @returns 不依赖 Node、pnpm、SSH 或手工解包的 POSIX shell 脚本。\n * @example 模块内部上下文\n * ```ts\n * const script = createLocalInstallScript({ bundle: 'bundle-shop-1.0.0.tar', directory: '/opt/hai/apps/shop-prod' })\n * // 保存为与 tar 同目录的 deploy-local.sh,目标 Linux 直接执行 sh deploy-local.sh。\n * ```\n */\nexport function createLocalInstallScript(options: { bundle: string, directory: string }): string {\n return String.raw`#!/bin/sh\n# 目标服务器本地入口:把整个交付目录复制到 Linux,直接执行 sh deploy-local.sh [服务器部署目录]。\n# 自动解包到本次独立临时目录并调用 apply.sh;不需要手工解包,也不需要 SSH、Node 或 pnpm。\n# 需要 tar、mktemp 和 apply.sh 所列的容器运行环境;全量/增量由 manifest.json 固定,增量要求已有成功基线。\n# 执行日志保留在本交付目录,退出时只清理本次临时解包目录,业务数据由 apply.sh 保留。\nset -eu\numask 077\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\nbundle=@@BUNDLE@@\ndestination=@@DIRECTORY@@\nif [ \"$#\" -gt 0 ]; then destination=$1; fi\nfor tool in tar mktemp date; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\ntest -f \"$source_dir/$bundle\" || { printf 'Bundle missing: %s\\n' \"$bundle\" >&2; exit 1; }\nlog=\"$source_dir/deploy-local-$(date +%Y%m%d-%H%M%S)-$$.log\"\ntemporary=$(mktemp -d /tmp/hai-deploy.XXXXXX)\ncleanup() { rm -rf -- \"$temporary\"; }\ntrap cleanup EXIT\ntrap 'exit 130' HUP INT TERM\nprintf 'Deployment log: %s\\n' \"$log\"\nif (tar -xf \"$source_dir/$bundle\" -C \"$temporary\" && sh \"$temporary/apply.sh\" \"$destination\") > \"$log\" 2>&1; then\n cat \"$log\"\nelse\n code=$?\n cat \"$log\" >&2\n exit \"$code\"\nfi\n`.replace('@@BUNDLE@@', shellArgument(options.bundle)).replace('@@DIRECTORY@@', shellArgument(options.directory))\n}\n","/**\n * @h-ai/deploy — SSH 执行器\n *\n * 基于用户机器已有的 OpenSSH 客户端(ssh / scp)封装远程命令执行与文件上传。\n * 复用 ~/.ssh/config、ssh-agent 与 OpenSSH 证书,避免引入 Node SSH SDK 的密钥兼容问题。\n * 所有调用均以 command + args 数组构造,禁止字符串拼接,防止命令注入。\n * @module deploy-ssh\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { SshConfig } from '../deploy-config.js'\nimport type { CommandOptions, CommandResult } from './deploy-command.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { getDeployCommandState } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { runCommand } from './deploy-command.js'\nimport { prepareSshAskpass } from './deploy-ssh-askpass.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'ssh' })\n\n/**\n * SSH 执行器接口\n * 命令通过远端登录 shell 执行;传入的命令文本必须由受信代码构造。远端副作用与本地 SSH 退出状态分开处理。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const ssh = createSshExecutor(config)\n * const connected = await ssh.ping()\n * if (!connected.success) throw new Error(connected.error.message)\n * ```\n */\nexport interface SshExecutor {\n /** 在远程主机执行命令(通过远程登录 shell 运行) */\n exec: (remoteCommand: string, options?: Pick<CommandOptions, 'timeoutMs' | 'terminationTimeoutMs' | 'secrets' | 'maxCaptureChars' | 'onOutput'>) => Promise<HaiResult<CommandResult>>\n /** 上传本地文件到远程路径 */\n upload: (localPath: string, remotePath: string) => Promise<HaiResult<void>>\n /** 远程连通性预检(执行 true 命令) */\n ping: () => Promise<HaiResult<void>>\n}\n\n/**\n * 显式 key 优先;空密码不会改变省略 auth 时的原 key/agent 默认行为。\n * @example 模块内部上下文\n * ```ts\n * function inspectAuthentication(password: string) {\n * const inferred = usesSshPassword({ password })\n * const explicitKey = usesSshPassword({ auth: 'key', password })\n * return { inferred, explicitKey }\n * }\n * ```\n */\nexport function usesSshPassword(config: Pick<SshConfig, 'auth' | 'password'>): boolean {\n return config.auth === 'password' || (config.auth === undefined && Boolean(config.password))\n}\n\n/** 构造 ssh 公共连接选项;密码从 child env 供给,不进入参数。 */\nfunction buildConnectOptions(config: SshConfig): string[] {\n const password = usesSshPassword(config)\n const args: string[] = ['-o', password ? 'BatchMode=no' : 'BatchMode=yes']\n if (password)\n args.push('-o', 'PreferredAuthentications=password', '-o', 'PasswordAuthentication=yes', '-o', 'PubkeyAuthentication=no', '-o', 'NumberOfPasswordPrompts=1')\n args.push('-o', `ConnectTimeout=${config.connectTimeoutSeconds}`)\n args.push('-o', `StrictHostKeyChecking=${config.strictHostKeyChecking ? 'accept-new' : 'no'}`)\n if (config.knownHostsFile) {\n // OpenSSH 会再次按配置语法解析 -o 的值,路径中的空格须保留内部引号。\n const path = config.knownHostsFile.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')\n args.push('-o', `UserKnownHostsFile=\"${path}\"`)\n }\n if (!password && config.identityFile) {\n args.push('-i', config.identityFile)\n args.push('-o', 'IdentitiesOnly=yes')\n }\n return args\n}\n\n/**\n * 构造 ssh 执行命令的参数数组。\n *\n * remoteCommand 作为单个参数传入,不经过本地 shell 解析,避免本地命令注入。\n * @param config - SSH 连接配置\n * @param remoteCommand - 远程命令字符串\n * @returns 交给本地 ssh 可执行文件的参数数组。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const args = buildSshExecArgs(config, 'true')\n * // 参数供本地无 shell 的 ssh 进程使用;不是可再次拼接进 shell 的字符串。\n * ```\n */\nexport function buildSshExecArgs(config: SshConfig, remoteCommand: string): string[] {\n return [\n ...buildConnectOptions(config),\n '-p',\n String(config.port),\n `${config.username}@${config.host}`,\n remoteCommand,\n ]\n}\n\n/**\n * 构造 scp 上传命令的参数数组。\n * 保留参数数组边界;远端路径只使用内部已校验的部署目录。\n * @param config - SSH 连接配置\n * @param localPath - 本地文件路径\n * @param remotePath - 远程目标路径\n * @returns 交给本地 scp 可执行文件的参数数组。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const args = buildScpUploadArgs(config, '/workspace/shop/.hai/deploy/shop.tar', '/opt/hai/incoming/shop.tar')\n * ```\n */\nexport function buildScpUploadArgs(config: SshConfig, localPath: string, remotePath: string): string[] {\n return [\n ...buildConnectOptions(config),\n '-P',\n String(config.port),\n localPath,\n `${config.username}@${config.host.includes(':') ? `[${config.host}]` : config.host}:${remotePath}`,\n ]\n}\n\n/**\n * 创建 SSH 执行器。\n * 创建执行器不持有长连接;每次 exec/upload/ping 启动独立受管理本地进程并检查 HaiResult。\n * @param config - SSH 连接配置\n * @returns SSH 执行器实例\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const ssh = createSshExecutor(config)\n * const connected = await ssh.ping()\n * if (!connected.success) throw new Error(connected.error.message)\n * ```\n */\nexport function createSshExecutor(config: SshConfig): SshExecutor {\n /** 密码 helper 与实际 SSH 共用预算;不引入全局凭据缓存或长连接生命周期。 */\n const runAuthenticated = async (command: string, args: string[], options: CommandOptions): Promise<HaiResult<CommandResult>> => {\n if (!usesSshPassword(config))\n return runCommand(command, args, options)\n if (!config.password || (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > 2147483647)))\n return err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM('deploy_sshPasswordInvalid'), ext: { commandExecution: { reason: 'configuration', localTermination: 'not-started' } } })\n const deadline = options.timeoutMs === undefined ? Number.POSITIVE_INFINITY : performance.now() + options.timeoutMs\n const prepared = await prepareSshAskpass(config.password, deadline, options.terminationTimeoutMs)\n if (!prepared.success)\n return prepared\n let result: HaiResult<CommandResult>\n let removed: HaiResult<void> = ok(undefined)\n try {\n const remaining = deadline - performance.now()\n result = remaining <= 0\n ? err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM('deploy_sshAskpassFailed'), ext: { commandExecution: { reason: 'timeout', localTermination: 'not-started' } } })\n : await runCommand(command, args, {\n ...options,\n env: prepared.data.env,\n timeoutMs: Number.isFinite(deadline) ? Math.ceil(remaining) : undefined,\n secrets: [...(options.secrets ?? []), config.password],\n })\n }\n catch {\n result = err({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: deployM('deploy_sshAskpassFailed'), ext: { commandExecution: { reason: 'configuration', localTermination: 'unknown' } } })\n }\n finally {\n removed = prepared.data.cleanup()\n }\n if (!removed.success)\n return result.success ? removed : err({ ...result.error, message: `${result.error.message}\\n${removed.error.message}` })\n return result\n }\n\n const exec: SshExecutor['exec'] = async (remoteCommand, options) => {\n const result = await runAuthenticated('ssh', buildSshExecArgs(config, remoteCommand), {\n timeoutMs: options?.timeoutMs,\n terminationTimeoutMs: options?.terminationTimeoutMs,\n maxCaptureChars: options?.maxCaptureChars,\n secrets: options?.secrets,\n onOutput: options?.onOutput,\n })\n if (result.success)\n return result\n const state = getDeployCommandState(result.error)\n // 连接客户端退出并不能证明远端进程结束;只增加安全状态,不暴露远程命令原文。\n return err({ ...result.error, suggestion: deployM('deploy_remoteUnknown'), ext: { ...result.error.ext, commandExecution: { ...state, reason: state?.reason ?? 'exit', localTermination: state?.localTermination ?? 'unknown', remoteExecution: 'unknown' } } })\n }\n\n const upload: SshExecutor['upload'] = async (localPath, remotePath) => {\n const args = buildScpUploadArgs(config, localPath, remotePath)\n const result = await runAuthenticated('scp', args, { timeoutMs: 600_000 })\n if (!result.success) {\n return err({ ...HaiDeployError.IMAGE_TRANSFER_FAILED, message: deployM('deploy_imageTransferFailed', { params: { error: result.error.message } }), ext: result.error.ext })\n }\n return ok(undefined)\n }\n\n const ping: SshExecutor['ping'] = async () => {\n logger.debug('SSH preflight', { host: config.host, port: config.port })\n const result = await exec('true', { timeoutMs: 20_000 })\n if (!result.success) {\n return err({ ...HaiDeployError.REMOTE_CONNECT_FAILED, message: deployM('deploy_remoteConnectFailed', { params: { host: config.host, error: result.error.message } }), ext: result.error.ext })\n }\n return ok(undefined)\n }\n\n return { exec, upload, ping }\n}\n","import type { Buffer } from 'node:buffer'\n/** 完整或增量交付包,包含所选服务需要的全部镜像及跨平台部署入口。 */\nimport type { DeploymentArtifact } from '../deploy-artifact.js'\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport { createHash } from 'node:crypto'\nimport { chmodSync, copyFileSync, createReadStream, createWriteStream, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { Transform } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport { parse } from 'yaml'\nimport { artifactChecksum } from '../deploy-artifact.js'\nimport { deployM } from '../deploy-i18n.js'\nimport { createBackendStateAssets } from './deploy-backend-state.js'\nimport { runCommand } from './deploy-command.js'\nimport { createManagedSecretAssets } from './deploy-managed-secrets.js'\nimport { createApplyScript, createLocalInstallScript, createUploadScripts } from './deploy-scripts.js'\nimport { usesSshPassword } from './deploy-ssh.js'\n\n/**\n * 打包所选服务;完整交付自动导出中间件,服务器启动时禁止联网拉取。\n * @throws Error - 制品、Compose、文件读取、镜像导出或打包失败;包含私有运行环境的 tar 必须按秘密传输与保存。\n * @param options - 本次操作选项;字段含义见各子项。\n * @param options.directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @param options.artifactDir - 已经验证的镜像 tar 与 manifest 所在目录。\n * @param options.artifact - 已通过结构、路径和文件摘要验证的构建清单。\n * @param options.projectName - 已归一化的项目名称。\n * @param options.deploymentId - 本次不可变部署标识,用于结果匹配和发布目录。\n * @param options.environment - 部署环境标识,通常为 prod。\n * @param options.config - 已通过 Schema 解析的 docker-ssh 配置。\n * @param options.runtime - 容器引擎策略;auto 探测可用引擎并优先 Podman。\n * @param options.output - 本次独立交付目录内的最终 tar 输出路径。\n * @param options.selected - 本次选择更新的 Compose 服务。\n * @param options.partial - 是否为增量服务部署;不能据此执行首次全量安装。\n * @param options.middlewareEnv - 应用增量继承的框架 HAI_* dotenv;镜像原生变量从独立文件读取。\n * @param options.accountSources - 初始账号变量名及来源,不包含密码值。\n * @param options.healthPaths - 允许执行的应用健康检查路径。\n * @param options.hasWebConfig - 是否挂载公开Nginx配置,包含前后端代理或独立Vite目录路由。\n * @param options.proxyService - 挂载 Nginx 配置的服务;缺省为 web,SSR/API 的存储网关为 gateway。\n * @param options.storageRouting - 自建 S3 非敏感连接/访问配置摘要,阻止增量配置与已装基线不一致。\n * @param options.containerPort - 应用容器的实际监听端口。\n * @param options.httpsAssets - 已校验的 HTTPS 证书与脚本附件。\n * @param options.cacheDirectory - 按镜像内容身份组织的私有归档缓存。\n * @returns tar 路径、手工执行说明及启动脚本名。\n * @example 模块内部上下文\n * ```ts\n * const { readDeploymentArtifact } = await import('../deploy-artifact.js')\n * const artifactDir = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(artifactDir)\n * // directory 已由 Provider 准备好 docker-compose-<版本>.yml 与 .env.runtime。\n * const directory = '.hai/deploy/prod/prepared-id'\n * const result = await createDeploymentBundle({ directory, artifactDir, artifact, projectName: 'shop', deploymentId: 'shop-prod-001', environment: 'prod', config: { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } }, runtime: 'auto', output: '.hai/deploy/shop.tar', selected: ['serv'], partial: false, middlewareEnv: '', healthPaths: ['/health'], hasWebConfig: false, containerPort: 3000 })\n * ```\n */\nexport async function createDeploymentBundle(options: {\n directory: string\n artifactDir: string\n artifact: DeploymentArtifact\n projectName: string\n deploymentId: string\n environment: string\n config: DockerSshProviderConfig\n runtime: 'auto' | 'podman' | 'docker'\n output: string\n selected: string[]\n partial: boolean\n middlewareEnv: string\n /** 初始账号变量名与配置来源,不包含变量值。 */\n accountSources?: string\n healthPaths: string[]\n hasWebConfig: boolean\n proxyService?: 'web' | 'gateway'\n storageRouting?: string\n containerPort: number\n /** HTTPS 附件已在写入交付目录前校验证书与域名。 */\n httpsAssets?: Record<string, string>\n /** 按镜像内容身份复用的本地归档缓存;命中仍核验实际归档。 */\n cacheDirectory?: string\n}): Promise<{ bundlePath: string, instructions: string, startName: string }> {\n const { directory, artifactDir, artifact, projectName, environment, config, selected } = options\n const output = resolve(options.output)\n if (!/^[\\w.+-]+\\.tar(?:\\.gz)?$/.test(basename(output)))\n throw new Error(deployM('deploy_bundleNameInvalid'))\n const staging = mkdtempSync(join(directory, '.bundle-'))\n const temporaryTar = `${output}.partial`\n mkdirSync(dirname(output), { recursive: true, mode: 0o700 })\n chmodSync(staging, 0o700)\n const files: string[] = []\n const fileHashes = new Map<string, string>()\n const put = (file: string, content: string): void => {\n mkdirSync(dirname(join(staging, file)), { recursive: true })\n writeFileSync(join(staging, file), content, { mode: 0o600 })\n files.push(file)\n }\n try {\n mkdirSync(join(staging, 'images'))\n const compose = parse(readFileSync(join(directory, `docker-compose-${artifact.appVersion}.yml`), 'utf8')) as {\n services: Record<string, Record<string, unknown>>\n networks?: Record<string, unknown>\n volumes?: Record<string, unknown>\n }\n const dependencies = new Set<string>()\n const references = new Set<string>()\n for (const name of selected) {\n const service = compose.services[name]\n if (!service)\n throw new Error(deployM('deploy_selectionInvalid', { params: { service: name } }))\n if (typeof service.image === 'string')\n references.add(service.image)\n if (service.depends_on) {\n for (const dependency of Array.isArray(service.depends_on) ? service.depends_on as string[] : Object.keys(service.depends_on))\n dependencies.add(dependency)\n }\n if (service.env_file) {\n service.env_file = name === artifact.primaryService\n ? [`../${options.deploymentId}/.env.runtime`, `../${options.deploymentId}/middleware.env`]\n : [`../${options.deploymentId}/middleware-runtime.env`]\n }\n if (Array.isArray(service.volumes))\n service.volumes = service.volumes.map(mount => typeof mount === 'string' ? mount.replace(/\\.\\/(web\\.conf|request-access\\.yml|tls|https-start\\.sh|renew-https\\.sh|\\.env\\.runtime|middleware\\.env|runtime-env\\.mjs):/g, `../${options.deploymentId}/$1:`) : mount)\n }\n put('compose.json', JSON.stringify({ ...compose, services: Object.fromEntries(selected.map(name => [name, compose.services[name]])) }))\n // 合并入口仅保存 extends 指向;更新服务时整体切换定义,避免旧 env_file/卷列表累加。\n put('compose-entry.json', JSON.stringify({ ...compose, services: Object.fromEntries(selected.map(name => [name, { extends: { file: `../${options.deploymentId}/compose.json`, service: name } }])) }))\n let runtime: 'podman' | 'docker' | undefined\n const imageList: string[] = []\n for (const reference of references) {\n if (!/:[^/:]+$/.test(reference) || /:latest$/i.test(reference))\n throw new Error(deployM('deploy_imageVersionRequired', { params: { image: reference } }))\n const built = artifact.images.find(image => image.imageRef === reference)\n const file = built?.file ?? `middleware-${imageList.length + 1}.tar`\n const destination = join(staging, 'images', file)\n if (built) {\n const checksum = await copyArchive(join(artifactDir, file), destination)\n if (checksum !== built.sha256)\n throw new Error(deployM('deploy_artifactInvalid'))\n fileHashes.set(`images/${file}`, checksum)\n }\n else {\n if (!runtime) {\n const candidates = options.runtime === 'auto' ? ['podman', 'docker'] as const : [options.runtime]\n for (const candidate of candidates) {\n if ((await runCommand(candidate, ['version'])).success) {\n runtime = candidate\n break\n }\n }\n if (!runtime)\n throw new Error(deployM('deploy_bundleRuntimeRequired'))\n }\n let inspected = await runCommand(runtime, ['image', 'inspect', '--format', '{{.Id}}', reference])\n if (!inspected.success) {\n const pulled = await runCommand(runtime, ['pull', reference], { timeoutMs: 600_000 })\n if (!pulled.success)\n throw new Error(pulled.error.message)\n inspected = await runCommand(runtime, ['image', 'inspect', '--format', '{{.Id}}', reference])\n }\n const identity = inspected.success && !inspected.data.stdoutTruncated ? inspected.data.stdout.trim().replace(/^sha256:/, '') : ''\n // 导出的归档保留请求的镜像标签;相同内容的不同引用不能直接共用该归档。\n const cacheIdentity = createHash('sha256').update(identity).update('\\0').update(reference).digest('hex')\n const cache = options.cacheDirectory && /^[a-f0-9]{64}$/.test(identity) ? join(options.cacheDirectory, `${runtime}-${cacheIdentity}.tar`) : undefined\n let checksum: string | undefined\n if (cache && existsSync(cache) && existsSync(`${cache}.sha256`) && lstatSync(cache).isFile() && !lstatSync(cache).isSymbolicLink()) {\n const copied = await copyArchive(cache, destination)\n if (copied === readFileSync(`${cache}.sha256`, 'utf8').trim())\n checksum = copied\n }\n if (!checksum) {\n const saved = await runCommand(runtime, ['save', ...(runtime === 'podman' ? ['--format', 'docker-archive'] : []), '-o', destination, reference], { timeoutMs: 600_000 })\n if (!saved.success)\n throw new Error(saved.error.message)\n checksum = await artifactChecksum(destination)\n if (cache) {\n mkdirSync(dirname(cache), { recursive: true, mode: 0o700 })\n // 不发布半写入缓存;并发打包使用各自的临时文件。\n const temporary = `${cache}.${basename(staging)}`\n try {\n copyFileSync(destination, temporary)\n renameSync(temporary, cache)\n writeFileSync(`${cache}.sha256`, `${checksum}\\n`, { mode: 0o600 })\n }\n finally {\n rmSync(temporary, { force: true })\n }\n }\n }\n fileHashes.set(`images/${file}`, checksum)\n }\n files.push(`images/${file}`)\n imageList.push(`${file} ${reference}`)\n }\n put('.env.runtime', readFileSync(join(directory, '.env.runtime'), 'utf8'))\n if (selected.includes(artifact.primaryService) && existsSync(join(directory, 'request-access.yml')))\n put('request-access.yml', readFileSync(join(directory, 'request-access.yml'), 'utf8'))\n put('middleware.env', options.middlewareEnv)\n if (selected.includes(artifact.primaryService) && !compose.services[artifact.primaryService]?.env_file)\n put('runtime-env.mjs', readFileSync(new URL('./deploy-runtime-env.mjs', import.meta.url), 'utf8'))\n const middlewareRuntime = join(directory, 'middleware-runtime.env')\n const nativeEnvironment = existsSync(middlewareRuntime) ? readFileSync(middlewareRuntime, 'utf8') : ''\n put('middleware-runtime.env', nativeEnvironment)\n for (const [file, content] of Object.entries(createManagedSecretAssets(projectName, nativeEnvironment, compose)))\n put(file, content)\n if (options.hasWebConfig)\n put('web.conf', readFileSync(join(directory, 'web.conf'), 'utf8'))\n for (const [file, content] of Object.entries(options.httpsAssets ?? {}))\n put(file, content)\n put('manifest.json', `${JSON.stringify({ ...artifact, images: artifact.images.filter(image => references.has(image.imageRef)), deploymentId: options.deploymentId, selectedServices: selected, partial: options.partial }, null, 2)}\\n`)\n if (options.hasWebConfig) {\n // 增量部署复用当前 Web 镜像,只覆盖公开代理配置;无需重新构建或打包 Web 镜像。\n put('proxy-entry.json', JSON.stringify({ services: { [options.proxyService ?? 'web']: { volumes: [`../${options.deploymentId}/web.conf:/etc/nginx/conf.d/default.conf:ro`] } } }))\n }\n put('storage-routing', `${options.storageRouting ?? ''}\\n`)\n const httpsFingerprint = config.expose.https ? createHash('sha256').update(JSON.stringify({ ...config.expose.https, certificateFile: undefined, privateKeyFile: undefined, certificate: options.httpsAssets?.['tls/fullchain.pem'] })).digest('hex') : ''\n put('layout', `${config.expose.hostPort}:${options.containerPort}:${options.hasWebConfig ? options.proxyService === 'gateway' ? 'gateway' : 'true' : 'false'}:${artifact.primaryService}:${options.hasWebConfig ? await artifactChecksum(join(directory, 'web.conf')) : ''}${httpsFingerprint ? `:${httpsFingerprint}` : ''}\\n`)\n put('web-base-path', `${artifact.webBasePath ?? ''}\\n`)\n put('health-paths', `${options.healthPaths.join('\\n')}\\n`)\n put('image-list', `${imageList.join('\\n')}\\n`)\n put('dependencies', `${[...dependencies].join('\\n')}\\n`)\n // 卷身份和引擎随校验和交付;服务器持久账本不会随暂时移除服务而删除。\n for (const [file, content] of Object.entries(createBackendStateAssets(projectName, compose, selected)))\n put(file, content)\n put('apply.sh', createApplyScript({ deploymentId: options.deploymentId, projectName, environment, directory: `${config.remote.baseDir}/${projectName}`, runtime: config.remote.runtime, partial: options.partial, selected, primaryService: artifact.primaryService, hostPort: config.expose.hostPort, healthPaths: options.healthPaths }))\n const instructionParams = { file: basename(output), start: 'apply.sh', images: [...references].join('\\n'), compose: 'compose.json' }\n const mode = deployM(options.partial ? 'deploy_bundlePartial' : 'deploy_bundleFull')\n const selection = deployM('deploy_bundleSelection', { params: { mode, services: selected.join(', ') } })\n const instructions = `${selection}\\n${deployM('deploy_bundleInstructions', { params: instructionParams })}`\n const runtimeGuide = deployM('deploy_bundleRuntime', { params: { directory: `${config.remote.baseDir}/${projectName}`, deploymentId: options.deploymentId } })\n const https = config.expose.https\n const serverDirectory = `${config.remote.baseDir}/${projectName}`\n const certificates = https?.type === 'files' ? `${serverDirectory}/releases/${options.deploymentId}/tls` : `${serverDirectory}/https/certificates/${https?.domain}`\n const httpsGuide = https\n ? deployM('deploy_bundleHttps', { params: { domain: https.domain, port: https.port, mode: https.type, certificates, environment } })\n + (https.type === 'letsencrypt' ? `\\n${deployM('deploy_bundleAcme', { params: { state: `${serverDirectory}/https/acme`, domain: https.domain } })}` : '')\n : deployM('deploy_bundleHttpOnly', { params: { port: config.expose.hostPort } })\n const accountGuide = deployM('deploy_bundleAccounts', { params: { sources: options.accountSources || '—' } })\n const guides = [runtimeGuide, httpsGuide, accountGuide, deployM('deploy_bundleDirectories', { params: { directory: serverDirectory, deploymentId: options.deploymentId } })].join('\\n\\n')\n const readme = `${deployM('deploy_bundleMetadata', { params: { version: artifact.appVersion, buildId: artifact.buildId, deploymentId: options.deploymentId, compose: 'compose.json' } })}\\n${instructions}\\n\\n${guides}\\n`\n const checksums = []\n for (const file of files)\n checksums.push(`${fileHashes.get(file) ?? await artifactChecksum(join(staging, file))} ${file}`)\n writeFileSync(join(staging, 'SHA256SUMS'), `${checksums.join('\\n')}\\n`)\n const tar = await runCommand('tar', [output.endsWith('.gz') ? '-czf' : '-cf', temporaryTar, '-C', staging, '.'])\n if (!tar.success)\n throw new Error(tar.error.message)\n chmodSync(temporaryTar, 0o600)\n renameSync(temporaryTar, output)\n const upload = createUploadScripts()\n const scripts = directory\n // 部署配置、清单和镜像只保存在 tar 中,外层仅保留实际入口、目标与说明。\n writeFileSync(join(scripts, 'deploy.sh'), upload.sh, { mode: 0o700 })\n writeFileSync(join(scripts, 'deploy-local.sh'), createLocalInstallScript({ bundle: basename(output), directory: `${config.remote.baseDir}/${projectName}` }), { mode: 0o700 })\n writeFileSync(join(scripts, 'deploy.ps1'), upload.ps1)\n writeFileSync(join(scripts, 'read-target.awk'), upload.reader)\n const target = {\n host: config.ssh?.host ?? 'SERVER_HOST',\n port: config.ssh?.port ?? 22,\n username: config.ssh?.username ?? 'deploy',\n auth: config.ssh && usesSshPassword(config.ssh) ? 'password' : 'key',\n passwordEnv: 'HAI_DEPLOY_PROVIDER_SSH_PASSWORD',\n identityFile: config.ssh?.identityFile ?? '',\n knownHostsFile: config.ssh?.knownHostsFile ?? '',\n strictHostKeyChecking: config.ssh?.strictHostKeyChecking ?? true,\n connectTimeoutSeconds: config.ssh?.connectTimeoutSeconds ?? 10,\n directory: `${config.remote.baseDir}/${projectName}`,\n bundle: basename(output),\n }\n const comments = {\n host: deployM('deploy_targetHost'),\n port: deployM('deploy_targetPort'),\n username: deployM('deploy_targetUsername'),\n auth: deployM('deploy_targetAuth'),\n passwordEnv: deployM('deploy_targetPasswordEnv'),\n identityFile: deployM('deploy_targetIdentityFile'),\n knownHostsFile: deployM('deploy_targetKnownHostsFile'),\n strictHostKeyChecking: deployM('deploy_targetStrictHostKeyChecking'),\n connectTimeoutSeconds: deployM('deploy_targetConnectTimeoutSeconds'),\n directory: deployM('deploy_targetDirectory'),\n bundle: deployM('deploy_targetBundle'),\n }\n writeFileSync(join(scripts, 'deploy-target.json'), `${JSON.stringify({ ...target, _comments: comments }, null, 2)}\\n`)\n writeFileSync(join(scripts, 'README.txt'), readme)\n for (const file of [`docker-compose-${artifact.appVersion}.yml`, '.env.runtime', 'middleware-runtime.env', 'request-access.yml', ...(options.hasWebConfig ? ['web.conf'] : [])])\n rmSync(join(directory, file), { force: true })\n return { bundlePath: output, instructions: `${selection}\\n${deployM('deploy_bundleInstructions', { params: { ...instructionParams, file: output } })}\\n${guides}\\n${scripts}`, startName: 'apply.sh' }\n }\n finally {\n rmSync(staging, { recursive: true, force: true })\n rmSync(temporaryTar, { force: true })\n }\n}\n\n/** 复制与计算摘要共用一次顺序读取,避免每个大镜像复制后再读取一遍。 */\nasync function copyArchive(source: string, destination: string): Promise<string> {\n const hash = createHash('sha256')\n const digest = new Transform({\n transform(chunk: Buffer, _encoding, callback) {\n hash.update(chunk)\n callback(null, chunk)\n },\n })\n await pipeline(createReadStream(source), digest, createWriteStream(destination, { mode: 0o600 }))\n return hash.digest('hex')\n}\n","/** HTTPS 的证书交付、Nginx 入口和 Certbot 生命周期;所有应用类型共用。 */\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport { createPrivateKey, createPublicKey, X509Certificate } from 'node:crypto'\nimport { readFileSync, statSync } from 'node:fs'\nimport { isIP } from 'node:net'\nimport { resolve } from 'node:path'\nimport { deployM } from '../deploy-i18n.js'\nimport { shellArgument } from './deploy-scripts.js'\n\n/**\n * 官方 Certbot 客户端的固定版本,随离线包导出,目标服务器不拉取镜像。\n * @example 模块内部上下文\n * ```ts\n * const certbotImage = CERTBOT_IMAGE\n * ```\n */\nexport const CERTBOT_IMAGE = 'docker.io/certbot/certbot:v5.9.0'\n/**\n * Docker SSH 入口已校验的 HTTPS 配置。\n * @example 模块内部上下文\n * ```ts\n * const https: HttpsConfig = { type: 'files', domain: 'app.example.com', port: 443, redirectHttp: true, certificateFile: './tls/fullchain.pem', privateKeyFile: './tls/privkey.pem' }\n * ```\n */\ntype HttpsConfig = NonNullable<DockerSshProviderConfig['expose']['https']>\n\n/**\n * 校验本地 PEM 并生成受保护的部署附件;异常不包含证书或私钥原文。\n * @param config - 已解析的 HTTPS 设置。\n * @param projectDirectory - 相对证书路径的工程根。\n * @returns 包内附件;私钥只能保存到私密交付目录,不能复制到构建上下文。\n * @example 模块内部上下文\n * ```ts\n * // 申请脚本由实际 HTTPS 配置生成,不在示例中请求证书。\n * const assets = createHttpsAssets({ type: 'letsencrypt', domain: 'app.example.com', port: 443, redirectHttp: true, email: 'ops@example.com', acceptTerms: true }, '.')\n * ```\n */\nexport function createHttpsAssets(config: HttpsConfig, projectDirectory: string): Record<string, string> {\n const assets: Record<string, string> = {\n https: `${config.domain} ${config.port} ${config.type}\\n`,\n }\n if (config.type === 'files') {\n try {\n const readPem = (file: string): string => {\n const path = resolve(projectDirectory, file)\n if (!statSync(path).isFile() || statSync(path).size > 1048576)\n throw new Error('Invalid PEM file')\n return readFileSync(path, 'utf8')\n }\n const certificate = readPem(config.certificateFile)\n const key = readPem(config.privateKeyFile)\n const parsed = new X509Certificate(certificate)\n const publicKey = createPublicKey(createPrivateKey(key)).export({ type: 'spki', format: 'der' })\n const now = Date.now()\n if (!publicKey.equals(parsed.publicKey.export({ type: 'spki', format: 'der' }))\n || now < Date.parse(parsed.validFrom) || now >= Date.parse(parsed.validTo)\n || !(isIP(config.domain) ? parsed.checkIP(config.domain) : parsed.checkHost(config.domain))) {\n throw new Error('Certificate validation failed')\n }\n assets['tls/fullchain.pem'] = certificate\n assets['tls/privkey.pem'] = key\n }\n catch {\n throw new Error(deployM('deploy_httpsCertificateInvalid'))\n }\n }\n else {\n assets['renew-https.sh'] = createRenewScript(config)\n }\n assets['prepare-https.sh'] = createPrepareScript(config)\n assets['https-start.sh'] = String.raw`#!/bin/sh\nset -eu\n# 目录挂载允许原子替换证书;只有新证书通过 nginx -t 才重载。\nwatch_certificate() {\n previous=$(sha256sum /etc/nginx/tls/fullchain.pem)\n while sleep 60; do\n current=$(sha256sum /etc/nginx/tls/fullchain.pem) || continue\n if [ \"$previous\" != \"$current\" ]; then\n if nginx -t && nginx -s reload; then previous=$current; else printf '[ERROR] HTTPS certificate reload failed\\n' >&2; fi\n fi\n done\n}\nwatch_certificate &\nexec /docker-entrypoint.sh nginx -g 'daemon off;'\n`\n return assets\n}\n\n/**\n * 为已有静态/反向代理配置添加 TLS;健康检查和 ACME 挑战仍可通过内部 HTTP 入口访问。\n * @param source - 已校验的、仅含一个入口 server 的 Nginx 配置。\n * @param config - HTTPS 设置。\n * @param httpPort - Nginx 容器内原有监听端口。\n * @returns TLS 入口与 HTTP 跳转/挑战配置。\n * @example 模块内部上下文\n * ```ts\n * const https: HttpsConfig = { type: 'files', domain: 'app.example.com', port: 443, redirectHttp: true, certificateFile: './tls/fullchain.pem', privateKeyFile: './tls/privkey.pem' }\n * const nginx = renderHttpsProxy('server { listen 8080; server_name _; }', https, 8080)\n * ```\n */\nexport function renderHttpsProxy(source: string, config: HttpsConfig, httpPort: number): string {\n const publicPort = config.port === 443 ? '' : `:${config.port}`\n const challenge = ' location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; }\\n'\n const tls = source\n .replace(`listen ${httpPort};`, `listen ${httpPort === 8443 ? 8444 : 8443} ssl;\\n ssl_certificate /etc/nginx/tls/fullchain.pem;\\n ssl_certificate_key /etc/nginx/tls/privkey.pem;`)\n .replace('server_name _;', `server_name ${config.domain};`)\n .replaceAll('proxy_set_header X-Forwarded-Proto $scheme;', 'proxy_set_header X-Forwarded-Proto https;')\n const http = config.redirectHttp\n ? `server {\\n listen ${httpPort};\\n server_name ${config.domain};\\n${challenge} location ~ ^/_hai/(web-health|gateway-health)$ { access_log off; return 200 'ok'; }\\n location / { return 308 https://${config.domain}${publicPort}$request_uri; }\\n}\\n`\n : source.slice(source.indexOf('server {')).replace('server_name _;', `server_name ${config.domain};\\n${challenge}`)\n return `${tls}\\n${http}`\n}\n\n/** 签发成功后才覆盖公开目录;目录上层为 0700,Nginx 只读挂载证书子目录。 */\nconst publishCertificate = String.raw`publish_certificate() {\n certificate=\"/etc/letsencrypt/live/$domain\"\n test -s \"$certificate/fullchain.pem\" && test -s \"$certificate/privkey.pem\"\n cp \"$certificate/fullchain.pem\" /output/fullchain.pem.next\n cp \"$certificate/privkey.pem\" /output/privkey.pem.next\n chmod 444 /output/fullchain.pem.next /output/privkey.pem.next\n mv /output/privkey.pem.next /output/privkey.pem\n mv /output/fullchain.pem.next /output/fullchain.pem\n}\n`\n\nfunction createRenewScript(config: Extract<HttpsConfig, { type: 'letsencrypt' }>): string {\n return `#!/bin/sh\\nset -eu\\ndomain=${shellArgument(config.domain)}\\n${publishCertificate}${String.raw`\ntrap 'exit 0' TERM INT\n# Certbot 自己判断到期时间;同一官方客户端同时负责申请与续期,不实现 ACME 协议。\nwhile :; do\n if certbot renew --cert-name \"$domain\" --non-interactive; then\n if [ -s \"/etc/letsencrypt/live/$domain/fullchain.pem\" ]; then\n current=$(sha256sum \"/etc/letsencrypt/live/$domain/fullchain.pem\" | awk '{print $1}')\n installed=$(sha256sum /output/fullchain.pem | awk '{print $1}')\n if [ \"$current\" != \"$installed\" ]; then publish_certificate; fi\n fi\n else\n printf '[ERROR] Certbot renewal failed; the existing certificate remains installed\\n' >&2\n fi\n sleep 43200 & wait $! || exit 0\ndone\n`}`\n}\n\nfunction createPrepareScript(config: HttpsConfig): string {\n const header = `#!/bin/sh\\nset -eu\\numask 077\\nroot=$1\\nrelease=$2\\nruntime=$3\\nmode=$4\\ndomain=${shellArgument(config.domain)}\\n`\n if (config.type === 'files') {\n return header + String.raw`\ntest \"$mode\" != prepare || {\n # 宿主 root/release 保持私密;容器仅可读取独立挂载的证书目录。\n chmod 700 \"$root\" \"$release\"\n chmod 755 \"$release/tls\"\n chmod 444 \"$release/tls/fullchain.pem\" \"$release/tls/privkey.pem\"\n}\n`\n }\n const python = [\n 'from cryptography import x509',\n 'from cryptography.x509.oid import NameOID',\n 'from cryptography.hazmat.primitives import hashes, serialization',\n 'from cryptography.hazmat.primitives.asymmetric import ec',\n 'from datetime import datetime, timedelta, timezone',\n 'from pathlib import Path',\n 'import sys',\n 'name=sys.argv[1]',\n 'key=ec.generate_private_key(ec.SECP256R1())',\n 'subject=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,name)])',\n 'now=datetime.now(timezone.utc)',\n 'cert=x509.CertificateBuilder().subject_name(subject).issuer_name(subject).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=1)).not_valid_after(now+timedelta(days=1)).add_extension(x509.SubjectAlternativeName([x509.DNSName(name)]),False).sign(key,hashes.SHA256())',\n 'Path(\"/output/privkey.pem\").write_bytes(key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))',\n 'Path(\"/output/fullchain.pem\").write_bytes(cert.public_bytes(serialization.Encoding.PEM))',\n ].join('\\n')\n const publish = `set -eu\\ndomain=${shellArgument(config.domain)}\\n${publishCertificate}\\npublish_certificate\\n`\n return `${header}image=${shellArgument(CERTBOT_IMAGE)}\\nemail=${shellArgument(config.email)}\\nbootstrap=${shellArgument(python)}\\n${String.raw`\nstate=\"$root/https\"\ncertificates=\"$state/certificates/$domain\"\nmkdir -p \"$state/acme\" \"$state/webroot\" \"$certificates\"\nchmod 700 \"$root\" \"$state\" \"$state/acme\"\nchmod 755 \"$state/webroot\" \"$certificates\"\nif [ \"$mode\" = prepare ]; then\n if [ ! -s \"$certificates/fullchain.pem\" ] || [ ! -s \"$certificates/privkey.pem\" ]; then\n if [ \"$5\" = true ]; then printf 'HTTPS certificate state missing; create a full deployment.\\n' >&2; exit 1; fi\n # 临时证书只用于启动挑战入口;签发失败不得提交 current。\n \"$runtime\" run --rm --pull never --entrypoint python -v \"$certificates:/output\" \"$image\" -c \"$bootstrap\" \"$domain\"\n chmod 444 \"$certificates/fullchain.pem\" \"$certificates/privkey.pem\"\n fi\nelif [ \"$mode\" = issue ]; then\n \"$runtime\" run --rm --pull never -v \"$state/acme:/etc/letsencrypt\" -v \"$state/webroot:/var/www/certbot\" \"$image\" certonly --webroot --webroot-path /var/www/certbot --cert-name \"$domain\" --domain \"$domain\" --email \"$email\" --agree-tos --non-interactive --keep-until-expiring\n \"$runtime\" run --rm --pull never --entrypoint sh -v \"$state/acme:/etc/letsencrypt:ro\" -v \"$certificates:/output\" \"$image\" -c `}${shellArgument(publish)}\\nfi\\n`\n}\n","/**\n * @h-ai/deploy — 容器编排文件生成\n *\n * 根据应用扫描结果生成 compose 文件与运行期环境:按需为 db/cache/storage\n * 追加自建 sidecar 服务,并注入对应的 HAI_DB / HAI_CACHE / HAI_STORAGE 覆盖变量。\n * 敏感值仅写入受保护的环境文件,应用与中间件分开,禁止进入 compose 文件。\n * @module deploy-container-compose\n */\n\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport type { DeployAppOptions, ScanResult, ServiceType } from '../deploy-types.js'\nimport { randomBytes } from 'node:crypto'\nimport { TrustedProxiesSchema } from '@h-ai/core'\nimport { resolveTransportBodyLimits } from '@h-ai/crypto'\nimport { stringify } from 'yaml'\nimport { mergeEnvironmentLayers } from '../deploy-environment.js'\nimport { usesDefaultMiddleware } from '../deploy-functions.js'\nimport { mergeManagedMiddlewareConfig } from '../deploy-middleware-config.js'\nimport { CERTBOT_IMAGE } from './deploy-https.js'\n\n/** sidecar 镜像固定版本,避免 `:latest` 漂移导致行为变化。 */\nconst IMAGES = {\n postgres: 'docker.io/library/postgres:16.15-alpine',\n mysql: 'docker.io/library/mysql:8.4.11',\n redis: 'docker.io/library/redis:7.4.11-alpine',\n rustfs: 'ghcr.io/rustfs/rustfs:1.0.1',\n minio: 'ghcr.io/coollabsio/minio:RELEASE.2025-10-15T17-29-55Z',\n qdrant: 'docker.io/qdrant/qdrant:v1.19.2',\n pgvector: 'docker.io/pgvector/pgvector:0.8.0-pg17',\n chroma: 'docker.io/chromadb/chroma:1.5.5',\n ldap: 'docker.io/osixia/openldap:1.5.0',\n smtp: 'docker.io/axllent/mailpit:v1.27.4',\n nginx: 'docker.io/nginxinc/nginx-unprivileged:1.29.8-alpine',\n} as const\n\n// 这些变量还由启动代码直接读取,父级 YAML/JSON 不会替代其进程语义。\nconst PROCESS_ENV_KEYS = new Set([\n 'HAI_CORE_ENV',\n 'HAI_CRYPTO_TRANSPORT_SERVERKEYRING',\n 'HAI_ADMIN_DEFAULT_PASSWORD',\n 'HAI_AUDIT_ADMIN_PASSWORD',\n 'HAI_CONFIG_ADMIN_PASSWORD',\n 'HAI_BUSINESS_OPERATOR_PASSWORD',\n 'HAI_E2E',\n])\n\n// 旧版本曾把镜像原生变量保存到应用环境;读取旧配置时也不再传给业务容器。\nconst CONTAINER_ENV_KEYS = new Set([\n 'POSTGRES_USER',\n 'POSTGRES_PASSWORD',\n 'POSTGRES_DB',\n 'MYSQL_ROOT_PASSWORD',\n 'MYSQL_DATABASE',\n 'MYSQL_USER',\n 'MYSQL_PASSWORD',\n 'MINIO_ROOT_USER',\n 'MINIO_ROOT_PASSWORD',\n 'RUSTFS_ACCESS_KEY',\n 'RUSTFS_SECRET_KEY',\n 'RUSTFS_ADDRESS',\n 'RUSTFS_VOLUMES',\n 'RUSTFS_CONSOLE_ENABLE',\n 'LDAP_DOMAIN',\n 'LDAP_ORGANISATION',\n 'LDAP_ADMIN_PASSWORD',\n 'LDAP_TLS',\n])\n\n/**\n * compose 服务定义(结构化对象,交由 yaml 序列化)。\n * 内部 Compose 文档对象,不是公开部署配置 Schema。\n * @example 模块内部上下文\n * ```ts\n * const service: ComposeService = { image: 'registry.example.org/shop:1.0.0', ports: ['8080:3000'] }\n * ```\n */\ntype ComposeService = Record<string, unknown>\n\n/**\n * sidecar 规划结果。\n * 无中间件应用的空计划是合法输入;有连接时 env/secrets 可能含私密值,不能整体展示。\n * @example 模块内部上下文\n * ```ts\n * const sidecar: SidecarPlan = { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, containerEnv: {}, dependsOn: [], secrets: [] }\n * const yaml = generateComposeFile({ projectName: 'shop', appVersion: '1.0.0', imageRef: 'shop:1.0.0-build1', hostPort: 8080, containerPort: 3000, sidecar })\n * ```\n */\nexport interface SidecarPlan {\n /** 实际启用的自建服务 */\n services: ServiceType[]\n /** compose services 片段(不含 app) */\n composeServices: Record<string, ComposeService>\n /** 命名卷 */\n volumes: Record<string, unknown>\n /** 挂载到 主应用容器的卷(如 sqlite/lancedb 的本地数据目录持久化) */\n appVolumes: string[]\n /** 框架 HAI_* 配置,允许保存到工程环境并注入应用。 */\n env: Record<string, string>\n /** 镜像要求的原生变量,仅写 middleware-runtime.env 并注入中间件。 */\n containerEnv: Record<string, string>\n /** serv 服务的 depends_on 列表 */\n dependsOn: string[]\n /** 需要在日志中脱敏的敏感值 */\n secrets: string[]\n}\n\n/**\n * 运行期环境构建结果。\n * @example 模块内部上下文\n * ```ts\n * const plan: RuntimeEnvPlan = { env: { NODE_ENV: 'production' }, sidecar: { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, containerEnv: {}, dependsOn: [], secrets: [] } }\n * const content = serializeEnvFile(plan.env)\n * ```\n */\nexport interface RuntimeEnvPlan {\n /** 完整运行期环境(写入 .env.runtime) */\n env: Record<string, string>\n /** sidecar 规划 */\n sidecar: SidecarPlan\n}\n\n/** 生成随机密码(url 安全)。 */\nfunction generatePassword(): string {\n return randomBytes(24).toString('base64url')\n}\n\n/**\n * 生成首次部署的候选值,不读取或创建打包机长期凭据缓存。\n * 服务器 apply 阶段以项目自己的私有状态定稿,后续电脑生成的候选不会改密码。\n * @returns 本包的私有候选值。\n */\nfunction createSidecarCandidates(): Record<string, string> {\n return {\n dbPassword: generatePassword(),\n storagePassword: generatePassword(),\n ldapPassword: generatePassword(),\n }\n}\n\n/** 为 app 追加本地数据卷(sqlite / lancedb 等文件型后端持久化)。 */\nfunction addAppDataVolume(plan: SidecarPlan, projectName: string): void {\n const mount = `${projectName}-data:/app/data`\n if (!plan.appVolumes.includes(mount)) {\n plan.appVolumes.push(mount)\n plan.volumes[`${projectName}-data`] = null\n }\n}\n\n/** PostgreSQL sidecar。 */\nfunction planPostgresDb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('db')\n plan.dependsOn.push('db')\n plan.composeServices.db = {\n image: IMAGES.postgres,\n container_name: `hai-${projectName}-db`,\n restart: 'unless-stopped',\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-db-data:/var/lib/postgresql/data`],\n healthcheck: { test: ['CMD', 'pg_isready', '-h', '127.0.0.1', '-U', 'hai', '-d', 'hai'], interval: '2s', timeout: '5s', retries: 60 },\n networks: net,\n }\n plan.volumes[`${projectName}-db-data`] = null\n plan.containerEnv.POSTGRES_USER = 'hai'\n plan.containerEnv.POSTGRES_PASSWORD = password\n plan.containerEnv.POSTGRES_DB = 'hai'\n plan.env.HAI_DB = JSON.stringify({ type: 'postgresql', url: `postgresql://hai:${password}@db:5432/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** MySQL sidecar。 */\nfunction planMysqlDb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('db')\n plan.dependsOn.push('db')\n plan.composeServices.db = {\n image: IMAGES.mysql,\n container_name: `hai-${projectName}-db`,\n restart: 'unless-stopped',\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-db-data:/var/lib/mysql`],\n healthcheck: { test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --silent'], interval: '2s', timeout: '5s', retries: 60 },\n networks: net,\n }\n plan.volumes[`${projectName}-db-data`] = null\n plan.containerEnv.MYSQL_ROOT_PASSWORD = password\n plan.containerEnv.MYSQL_DATABASE = 'hai'\n plan.containerEnv.MYSQL_USER = 'hai'\n plan.containerEnv.MYSQL_PASSWORD = password\n plan.env.HAI_DB = JSON.stringify({ type: 'mysql', url: `mysql://hai:${password}@db:3306/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** Redis sidecar。 */\nfunction planRedisCache(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('cache')\n plan.dependsOn.push('cache')\n plan.composeServices.cache = {\n image: IMAGES.redis,\n container_name: `hai-${projectName}-cache`,\n restart: 'unless-stopped',\n healthcheck: { test: ['CMD', 'redis-cli', 'ping'], interval: '2s', timeout: '5s', retries: 60 },\n networks: net,\n }\n plan.env.HAI_CACHE = JSON.stringify({ type: 'redis', url: 'redis://cache:6379' })\n}\n\n/** S3 协议与服务实现分离;RustFS/MinIO 使用相同应用契约及幂等 bucket 初始化。 */\nfunction planS3Storage(plan: SidecarPlan, projectName: string, password: string, net: string[], engine: 'rustfs' | 'minio', configured: Record<string, unknown> = {}): void {\n plan.services.push('storage')\n plan.dependsOn.push('storage')\n plan.composeServices.storage = {\n image: IMAGES[engine],\n container_name: `hai-${projectName}-storage`,\n restart: 'unless-stopped',\n ...(engine === 'minio' ? { command: ['server', '/data'] } : {}),\n healthcheck: { test: engine === 'rustfs' ? ['CMD', 'curl', '--noproxy', '*', '-fsS', 'http://127.0.0.1:9000/minio/health/ready'] : ['CMD', 'mc', 'ready', 'http://127.0.0.1:9000'], interval: '2s', timeout: '5s', retries: 60 },\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-storage-data:/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-storage-data`] = null\n if (engine === 'rustfs') {\n Object.assign(plan.containerEnv, { RUSTFS_ACCESS_KEY: 'hai-storage', RUSTFS_SECRET_KEY: password, RUSTFS_ADDRESS: '0.0.0.0:9000', RUSTFS_VOLUMES: '/data', RUSTFS_CONSOLE_ENABLE: 'false' })\n }\n else {\n Object.assign(plan.containerEnv, { MINIO_ROOT_USER: 'hai-storage', MINIO_ROOT_PASSWORD: password })\n }\n plan.env.HAI_STORAGE = JSON.stringify({\n type: 's3',\n endpoint: 'http://storage:9000',\n bucket: configured.bucket || 'hai',\n region: configured.region || 'us-east-1',\n // 自建只替换连接和托管凭据,不能丢失对象前缀、外部签名地址或操作日志策略。\n ...Object.fromEntries(['prefix', 'publicEndpoint', 'publicUrl', 'operationLog'].filter(name => configured[name] !== undefined).map(name => [name, configured[name]])),\n accessKeyId: 'hai-storage',\n secretAccessKey: password,\n forcePathStyle: true,\n createBucket: true,\n })\n plan.env.HAI_STORAGE_CREATEBUCKET = 'true'\n plan.secrets.push(password)\n}\n\n/** Qdrant 向量库 sidecar。 */\nfunction planQdrantVecdb(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.qdrant,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n volumes: [`${projectName}-vecdb-data:/qdrant/storage`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n plan.env.HAI_VECDB = JSON.stringify({ type: 'qdrant', url: 'http://vecdb:6333' })\n}\n\n/** pgvector 向量库 sidecar(PostgreSQL + pgvector 扩展)。 */\nfunction planPgvectorVecdb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.pgvector,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n env_file: ['middleware-runtime.env'],\n volumes: [`${projectName}-vecdb-data:/var/lib/postgresql/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n // 与 postgres db sidecar 共用 POSTGRES_* 凭据(不同实例、不同卷,值一致即可)。\n plan.containerEnv.POSTGRES_USER = 'hai'\n plan.containerEnv.POSTGRES_PASSWORD = password\n plan.containerEnv.POSTGRES_DB = 'hai'\n plan.env.HAI_VECDB = JSON.stringify({ type: 'pgvector', url: `postgresql://hai:${password}@vecdb:5432/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** Chroma 向量库 sidecar。 */\nfunction planChromaVecdb(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.chroma,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n volumes: [`${projectName}-vecdb-data:/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n plan.env.HAI_VECDB = JSON.stringify({ type: 'chroma', url: 'http://vecdb:8000' })\n}\n\n/**\n * 解析 keep 策略;保留内部连接仍交付对应 sidecar,未选择的服务保持不变。\n * @param scan - 实际配置扫描结果。\n * @param options - 本次部署策略。\n * @returns 与执行端共用的有效策略,不读写文件或凭据。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const options = resolveSidecarOptions(scanned.data, { serviceModes: { db: 'keep' } })\n * ```\n */\nexport function resolveSidecarOptions(scan: ScanResult, options?: DeployAppOptions): DeployAppOptions {\n // 保持配置不变仍需交付自建服务镜像;已保存的容器服务地址可明确区分外部连接。\n const serviceModes = { ...options?.serviceModes }\n for (const requirement of scan.middlewares ?? []) {\n // 规划描述完整拓扑;selectedServices 只限制后续归档和更新,不能让未选自建依赖消失。\n const mode = serviceModes[requirement.envPrefix] ?? serviceModes[requirement.service]\n if (mode !== 'keep')\n continue\n const endpoint = requirement.config.url ?? requirement.config.endpoint\n let host = requirement.config.host\n if (typeof endpoint === 'string') {\n try {\n host = new URL(endpoint).hostname\n }\n catch {\n continue\n }\n }\n if (host === requirement.service || ['sqlite', 'local', 'memory', 'lancedb'].includes(requirement.backend)) {\n serviceModes[requirement.envPrefix] = 'default'\n serviceModes[requirement.service] = 'default'\n }\n }\n return { ...options, serviceModes }\n}\n\n/**\n * 复用实际编排规则生成 sidecar;secretValues 仅供只读计划提供空占位值,执行时生成私有候选。\n * 仅为 requiredServices 中采用 default 且无 Provisioner 配置的服务规划匹配后端;文件后端共用 app 数据卷。\n * @param _appDir - 调用方应用目录上下文;凭据不在此落盘。\n * @param projectName - 部署项目身份。\n * @param scan - 实际依赖与配置扫描结果。\n * @param provisionEnv - 已开通服务的环境变量。\n * @param options - 执行选项。\n * @param s3Engine - S3 服务实现。\n * @param secretValues - 内部规划的凭据占位值,不是公开配置。\n * @returns sidecar 计划,env 和 secrets 不得整体输出。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const sidecar = planSidecars(process.cwd(), 'shop', scanned.data, {}, { serviceModes: { db: 'keep' } })\n * ```\n */\nexport function planSidecars(\n _appDir: string,\n projectName: string,\n scan: ScanResult,\n provisionEnv: Record<string, string>,\n options?: DeployAppOptions,\n s3Engine: 'rustfs' | 'minio' = 'rustfs',\n secretValues?: Record<string, string>,\n): SidecarPlan {\n options = resolveSidecarOptions(scan, options)\n const plan: SidecarPlan = {\n services: [],\n composeServices: {},\n volumes: {},\n appVolumes: [],\n env: {},\n containerEnv: {},\n dependsOn: [],\n secrets: [],\n }\n // 全部保持不变时,不生成自建中间件候选。\n if (!scan.requiredServices.some(service => usesDefaultMiddleware(scan, service, options)))\n return plan\n const secrets = secretValues ?? createSidecarCandidates()\n const net = ['hai-app']\n const backends = scan.serviceBackends\n\n for (const service of scan.requiredServices) {\n if (!usesDefaultMiddleware(scan, service, options))\n continue\n if (service === 'db' && !provisionEnv.HAI_DB) {\n const backend = backends.db ?? 'postgresql'\n if (backend === 'mysql')\n planMysqlDb(plan, projectName, secrets.dbPassword, net)\n else if (backend === 'sqlite')\n addAppDataVolume(plan, projectName) // 文件库:仅持久化数据目录,保留应用自身 sqlite 配置\n else\n planPostgresDb(plan, projectName, secrets.dbPassword, net)\n }\n else if (service === 'cache' && !provisionEnv.HAI_CACHE) {\n if ((backends.cache ?? 'redis') === 'redis')\n planRedisCache(plan, projectName, net)\n }\n else if (service === 'storage' && !provisionEnv.HAI_STORAGE) {\n if ((backends.storage ?? 's3') === 's3')\n planS3Storage(plan, projectName, secrets.storagePassword, net, s3Engine, scan.middlewares?.find(item => item.service === 'storage')?.config)\n else\n addAppDataVolume(plan, projectName)\n }\n else if (service === 'vecdb' && !provisionEnv.HAI_VECDB) {\n const backend = backends.vecdb ?? 'qdrant'\n if (backend === 'pgvector')\n planPgvectorVecdb(plan, projectName, secrets.dbPassword, net)\n else if (backend === 'chroma')\n planChromaVecdb(plan, projectName, net)\n else if (backend === 'lancedb')\n addAppDataVolume(plan, projectName) // 嵌入式:持久化本地向量文件\n else\n planQdrantVecdb(plan, projectName, net)\n }\n else if (service === 'ldap' && backends.ldap === 'ldap' && !provisionEnv.HAI_IAM_LDAP) {\n const password = secrets.ldapPassword ?? secrets.dbPassword\n plan.services.push('ldap')\n plan.dependsOn.push('ldap')\n plan.composeServices.ldap = { image: IMAGES.ldap, restart: 'unless-stopped', env_file: ['middleware-runtime.env'], networks: net, volumes: [`${projectName}-ldap-data:/var/lib/ldap`, `${projectName}-ldap-config:/etc/ldap/slapd.d`] }\n plan.volumes[`${projectName}-ldap-data`] = null\n plan.volumes[`${projectName}-ldap-config`] = null\n Object.assign(plan.containerEnv, { LDAP_DOMAIN: 'example.org', LDAP_ORGANISATION: 'HAI', LDAP_ADMIN_PASSWORD: password, LDAP_TLS: 'false' })\n Object.assign(plan.env, { HAI_IAM_LOGIN_LDAP: 'true', HAI_IAM_LDAP: JSON.stringify({ url: 'ldap://ldap:389', bindDn: 'cn=admin,dc=example,dc=org', bindPassword: password, searchBase: 'dc=example,dc=org' }) })\n plan.secrets.push(password)\n }\n else if (service === 'email' && (scan.middlewares ? scan.middlewares.some(item => item.service === 'email' && item.backend === 'smtp' && (options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.email ?? 'default') === 'default') : backends.email === 'smtp') && !provisionEnv.HAI_REACH_PROVIDERS) {\n plan.services.push('email')\n plan.dependsOn.push('email')\n plan.composeServices.email = { image: IMAGES.smtp, restart: 'unless-stopped', networks: net }\n const requirements = scan.middlewares?.filter(item => item.service === 'email' && item.backend === 'smtp' && ['default', undefined].includes(options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.email))\n if (requirements?.length) {\n for (const requirement of requirements)\n plan.env[requirement.envPrefix] = JSON.stringify({ name: requirement.config.name ?? 'email', type: 'smtp', host: 'email', port: 1025, secure: false, from: requirement.config.from || 'noreply@example.com' })\n }\n else if (!scan.middlewares) {\n plan.env.HAI_REACH_PROVIDERS_0 = JSON.stringify({ name: 'email', type: 'smtp', host: 'email', port: 1025, secure: false, from: 'noreply@example.com' })\n }\n }\n }\n\n for (const requirement of scan.middlewares ?? []) {\n const supplied = plan.env[requirement.envPrefix]\n if (supplied)\n plan.env[requirement.envPrefix] = JSON.stringify(mergeManagedMiddlewareConfig(requirement, JSON.parse(supplied)))\n }\n return plan\n}\n\n/**\n * 构建运行期环境变量并规划 sidecar。\n *\n * 合并顺序(后者覆盖前者):目标环境默认 < 应用显式配置 < sidecar 自建 < Provisioner 输出。\n * NODE_ENV 默认按目标模式选择:dev/development 为 development,test 为 test,其余为 production。\n * @param appDir - 应用根目录\n * @param projectName - 项目名\n * @param scan - 扫描结果\n * @param provisionEnv - Provisioner 输出环境变量\n * @param containerPort - 容器内监听端口\n * @returns 运行期环境与 sidecar 规划\n * @param options - 本次操作选项;字段含义见各子项。\n * @param appEnv - 已加载的应用变量,和云开通结果分别传入。\n * @param s3Engine - 自建 S3 服务实现;协议仍为 s3,默认 rustfs。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const plan = buildRuntimeEnv(process.cwd(), 'shop', scanned.data, {}, 3000, { environment: 'prod' }, { NODE_ENV: 'production' })\n * const text = serializeEnvFile(plan.env)\n * ```\n */\nexport function buildRuntimeEnv(\n appDir: string,\n projectName: string,\n scan: ScanResult,\n provisionEnv: Record<string, string>,\n containerPort: number,\n options?: DeployAppOptions,\n appEnv: Record<string, string> = {},\n s3Engine: 'rustfs' | 'minio' = 'rustfs',\n): RuntimeEnvPlan {\n const sidecar = planSidecars(appDir, projectName, scan, provisionEnv, options, s3Engine)\n const environment = options?.environment ?? appEnv.HAI_DEPLOY_ENVIRONMENT ?? 'prod'\n const nodeEnv = environment === 'dev' || environment === 'development' ? 'development' : environment === 'test' ? 'test' : 'production'\n const env = mergeEnvironmentLayers([{\n NODE_ENV: nodeEnv,\n HOST: '0.0.0.0',\n PORT: String(containerPort),\n HAI_SERV_SERVER_HOST: '0.0.0.0',\n HAI_SERV_SERVER_PORT: String(containerPort),\n }, Object.fromEntries(Object.entries(appEnv).filter(([name]) => !CONTAINER_ENV_KEYS.has(name))), sidecar.env, provisionEnv])\n return { env, sidecar }\n}\n\n/**\n * 生成 compose 文件内容。\n * @param options - 生成参数\n * @param options.projectName - 项目名\n * @param options.imageRef - 应用镜像引用\n * @param options.appVersion - 应用发布版本,例如 1.2.3;不改变持久化卷身份\n * @param options.hostPort - 宿主机映射端口\n * @param options.https - 可选的统一 HTTPS 入口与 Certbot 设置。\n * @param options.containerPort - 容器内端口\n * @param options.primaryService - 主运行服务角色,独立 API 为 serv,浏览器站点为 web。\n * @param options.sidecar - sidecar 规划\n * @param options.web - 同一编排中的 Web 镜像与监听端口,独立于私有应用环境\n * @param options.web.imageRef - Web 镜像引用\n * @param options.web.containerPort - Web 容器监听端口\n * @param options.mountWebConfig - 独立Vite站点是否挂载公开的目录路由配置,默认不挂载。\n * @param options.gateway - SSR/API 自建对象存储的公开 Nginx 入口;只在没有现成 Web 代理时启用。\n * @param options.requestAccessPolicy - 是否为本次更新的后端挂载只读请求策略快照。\n * @param options.nodeRuntime - Node 后端默认重读运行文件;SSR web 显式标识。\n * @param options.nodeOptions - 打包时保留的 Node 启动参数,更新需重新部署。\n * @returns compose YAML 字符串\n * @example 模块内部上下文\n * ```ts\n * const sidecar: SidecarPlan = { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, containerEnv: {}, dependsOn: [], secrets: [] }\n * const yaml = generateComposeFile({ projectName: 'shop', appVersion: '1.0.0', imageRef: 'shop:1.0.0-build1', hostPort: 8080, containerPort: 3000, sidecar })\n * ```\n */\nexport function generateComposeFile(options: {\n projectName: string\n appVersion: string\n imageRef: string\n hostPort: number\n containerPort: number\n /** 独立 API 为 serv,独立静态或 SSR 站点为 web。 */\n primaryService?: 'serv' | 'web'\n sidecar: SidecarPlan\n /** Web 公开入口;私有运行环境仅属于 API 服务。 */\n web?: { imageRef: string, containerPort: number }\n mountWebConfig?: boolean\n gateway?: boolean\n /** 本次更新的服务挂载不可变、已验证的请求策略快照。 */\n requestAccessPolicy?: boolean\n /** Node 后端每次启动重读运行文件;serv 默认开启,SSR web 由扫描结果标识。 */\n nodeRuntime?: boolean\n /** 需要保留的 Node 启动参数;变化仍需重新部署容器。 */\n nodeOptions?: string\n /** HTTPS 与 Certbot 的统一入口设置。 */\n https?: DockerSshProviderConfig['expose']['https']\n}): string {\n const { projectName, imageRef, hostPort, containerPort, sidecar } = options\n const primaryService = options.primaryService ?? 'serv'\n const nodeRuntime = options.nodeRuntime ?? primaryService === 'serv'\n\n const app: ComposeService = {\n image: imageRef,\n labels: { 'org.opencontainers.image.version': options.appVersion },\n container_name: `hai-${projectName}-${primaryService}`,\n restart: 'unless-stopped',\n // 镜像已由 load 注入本地,禁止 compose 再从 registry 拉取\n pull_policy: 'never',\n env_file: ['.env.runtime'],\n ports: [`${hostPort}:${containerPort}`],\n networks: ['hai-app'],\n }\n if (primaryService === 'serv') {\n // 与应用相同的公开 Schema 和环境解析;不传 --input-type,避免预加载时传给日志 worker。\n app.healthcheck = {\n test: ['CMD', 'node', '-e', '(async () => { try { const { core } = await import(\\'@h-ai/core\\'); const { ServConfigSchema } = await import(\\'@h-ai/serv\\'); core.init({ configDir: \\'./config\\' }); const { server, http } = ServConfigSchema.parse(core.config.getOrThrow(\\'serv\\')); if (http.health === false) process.exit(0); const response = await fetch(\\'http://127.0.0.1:\\' + server.port + http.health.path, { signal: AbortSignal.timeout(4000) }); process.exit(response.ok ? 0 : 1); } catch { process.exit(1); } })()'],\n interval: '30s',\n timeout: '5s',\n start_period: '15s',\n retries: 3,\n }\n }\n const appVolumes = [...sidecar.appVolumes]\n const appEnvironment: Record<string, string> = {}\n if (nodeRuntime) {\n delete app.env_file\n appVolumes.push('./.env.runtime:/run/hai/.env.runtime:ro', './middleware.env:/run/hai/middleware.env:ro', './runtime-env.mjs:/run/hai/runtime-env.mjs:ro')\n appEnvironment.NODE_OPTIONS = (`--import /run/hai/runtime-env.mjs${options.nodeOptions ? ` ${options.nodeOptions}` : ''}`).replaceAll('$', () => '$$')\n }\n if (options.requestAccessPolicy)\n appVolumes.push('./request-access.yml:/run/hai/request-access.yml:ro')\n if (options.web || options.gateway)\n appEnvironment.HAI_DEPLOY_PRIVATE_PROXY = '1'\n if (Object.keys(appEnvironment).length)\n app.environment = appEnvironment\n if (options.mountWebConfig)\n appVolumes.push('./web.conf:/etc/nginx/conf.d/default.conf:ro')\n if (appVolumes.length)\n app.volumes = appVolumes\n if (sidecar.dependsOn.length > 0)\n app.depends_on = Object.fromEntries(sidecar.dependsOn.map(name => [name, { condition: sidecar.composeServices[name]?.healthcheck ? 'service_healthy' : 'service_started' }]))\n\n const services: Record<string, ComposeService> = { [primaryService]: app, ...sidecar.composeServices }\n if (options.web) {\n delete app.ports\n services.web = {\n image: options.web.imageRef,\n labels: { 'org.opencontainers.image.version': options.appVersion },\n container_name: `hai-${projectName}-web`,\n restart: 'unless-stopped',\n pull_policy: 'never',\n ports: [`${hostPort}:${options.web.containerPort}`],\n environment: { PUBLIC_API_BASE: '' },\n healthcheck: { test: ['CMD', 'wget', '-Y', 'off', '-q', '-O', '/dev/null', `http://127.0.0.1:${options.web.containerPort}/_hai/web-health`], interval: '30s', timeout: '5s', retries: 3 },\n volumes: ['./web.conf:/etc/nginx/conf.d/default.conf:ro'],\n depends_on: sidecar.services.includes('storage') ? ['serv', 'storage'] : ['serv'],\n networks: ['hai-app'],\n }\n }\n if (options.gateway) {\n delete app.ports\n services.gateway = {\n image: IMAGES.nginx,\n container_name: `hai-${projectName}-gateway`,\n restart: 'unless-stopped',\n ports: [`${hostPort}:8080`],\n healthcheck: { test: ['CMD', 'wget', '-Y', 'off', '-q', '-O', '/dev/null', 'http://127.0.0.1:8080/_hai/gateway-health'], interval: '30s', timeout: '5s', retries: 3 },\n volumes: ['./web.conf:/etc/nginx/conf.d/default.conf:ro'],\n depends_on: [primaryService, ...(sidecar.services.includes('storage') ? ['storage'] : [])],\n networks: ['hai-app'],\n }\n }\n if (options.https) {\n const proxy = services[options.gateway ? 'gateway' : options.web ? 'web' : primaryService]!\n const https = options.https\n const httpPort = options.gateway ? 8080 : options.web?.containerPort ?? containerPort\n proxy.ports = [...proxy.ports as string[], `${https.port}:${httpPort === 8443 ? 8444 : 8443}`]\n const certificates = https.type === 'files' ? './tls' : `../../https/certificates/${https.domain}`\n proxy.volumes = [\n ...proxy.volumes as string[],\n `${certificates}:/etc/nginx/tls:ro`,\n './https-start.sh:/run/hai/https-start.sh:ro',\n ...(https.type === 'letsencrypt' ? ['../../https/webroot:/var/www/certbot:ro'] : []),\n ]\n proxy.entrypoint = ['sh', '/run/hai/https-start.sh']\n if (https.type === 'letsencrypt') {\n services.certbot = {\n image: CERTBOT_IMAGE,\n restart: 'unless-stopped',\n entrypoint: ['sh', '/run/hai/renew-https.sh'],\n volumes: [\n '../../https/acme:/etc/letsencrypt',\n '../../https/webroot:/var/www/certbot',\n `../../https/certificates/${https.domain}:/output`,\n './renew-https.sh:/run/hai/renew-https.sh:ro',\n ],\n networks: ['hai-app'],\n }\n }\n }\n const compose: Record<string, unknown> = {\n 'x-hai-version': options.appVersion,\n services,\n 'networks': {\n 'hai-app': {},\n },\n }\n if (Object.keys(sidecar.volumes).length > 0)\n compose.volumes = sidecar.volumes\n\n for (const service of Object.values(services))\n service.pull_policy = 'never'\n return stringify(compose, { aliasDuplicateObjects: false })\n}\n\n/**\n * 生成同源 Web/API 的 Nginx 配置,保留运行时配置及 SPA 页面刷新。\n * API 上限由 @h-ai/crypto 的同一明文容量推导密文预算;\n * 关闭请求缓冲,让应用在读取过程中执行握手、公钥和正文的更细预算。\n * @param port - API 容器监听端口\n * @param apiPrefix - 应用实际 API 前缀,不允许向 Nginx 配置注入指令\n * @param options - Web 监听端口和双向业务明文 UTF-8 字节上限,缺省使用 crypto 默认值\n * @param options.webPort - Web 容器监听端口,默认 8080。\n * @param options.maxPlaintextBytes - 业务明文 UTF-8 字节上限。\n * @param options.webBasePath - 无末尾斜杠的Web挂载目录,缺省或空字符串为域名根目录。\n * @param options.storageBucket - 自建私有 S3 桶,配置后对象请求由 Nginx 直达 storage。\n * @param options.storageBasePath - 对象入口目录,转发前移除;空字符串保持根桶路径。\n * @param options.trustedEdgeProxies - Nginx 前方显式可信的负载均衡 IP/CIDR,默认不信任上游头。\n * @param options.backendPaths - 后端实际启用的健康、就绪及文档精确路径,认证仍由后端执行。\n * @returns 仅含公开路由的 Nginx 配置\n * @example 模块内部上下文\n * ```ts\n * const nginx = generateWebProxyConfig(3000, '/api', { webPort: 8080 }) // Web 将同源 /api 转发至 serv 服务。\n * ```\n */\nexport function generateWebProxyConfig(port: number, apiPrefix: string, options: { webPort?: number, maxPlaintextBytes?: number, webBasePath?: string, backendPaths?: string[], storageBucket?: string, storageBasePath?: string, trustedEdgeProxies?: string[] } = {}): string {\n const bodyLimits = resolveTransportBodyLimits(options.maxPlaintextBytes)\n const webPort = options.webPort ?? 8080\n const webBasePath = options.webBasePath ?? ''\n const apiPath = apiPrefix.replace(/\\/+$/, '')\n const backendPaths = [...new Set(options.backendPaths ?? ['/health'])]\n if (!/^\\/[\\w.-]+(?:\\/[\\w.-]+)*$/.test(apiPrefix) || apiPrefix.split('/').some(part => part === '.' || part === '..') || ![port, webPort].every(value => Number.isInteger(value) && value >= 1 && value <= 65535)\n || backendPaths.includes(`${webBasePath}/`)\n || backendPaths.some(path => !/^\\/[\\w./-]*$/.test(path) || path.includes('//') || path.split('/').some(part => part === '.' || part === '..') || path === `${webBasePath}/runtime-config.js` || path === '/_hai/web-health')\n || (webBasePath && (backendPaths.includes(webBasePath) || webBasePath === apiPath || webBasePath.startsWith(`${apiPath}/`)))) {\n throw new Error('Invalid web proxy target')\n }\n const webLocation = renderWebLocation(webBasePath)\n const storageLocation = options.storageBucket ? renderStorageLocation(options.storageBucket, [apiPath, ...backendPaths, ...(options.storageBasePath ? [`${webBasePath}/_app`, `${webBasePath}/assets`, `${webBasePath}/runtime-config.js`] : [webBasePath])], options.storageBasePath) : ''\n const backendLocations = backendPaths.map(path => ` location = ${path} {\n proxy_pass http://serv:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Real-IP $remote_addr;\n }\n`).join('')\n return `${options.storageBucket ? renderStorageUpstream(options.storageBucket, options.storageBasePath) : ''}server {\n listen ${webPort};\n server_name _;\n${renderTrustedEdgeProxies(options.trustedEdgeProxies)} root /usr/share/nginx/html;\n large_client_header_buffers 4 32k;\n${storageLocation}${webLocation} location = ${webBasePath}/runtime-config.js {\n add_header Cache-Control \"no-store\";\n default_type application/javascript;\n return 200 'globalThis.__HAI_PUBLIC_CONFIG__={apiBase:globalThis.location.origin+\"${apiPrefix}\"};';\n }\n location = /_hai/web-health {\n access_log off;\n return 200 'ok';\n }\n${backendLocations} location ${apiPrefix.replace(/\\/$/, '')}/ {\n client_max_body_size ${bodyLimits.encryptedPayloadBytes};\n proxy_pass http://serv:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_buffer_size 32k;\n proxy_buffers 8 32k;\n }\n}\n`\n}\n\n/**\n * 生成私有对象直连路由;不重写签名所绑定的 Host、原始 URI 和查询,不把大文件送进应用。\n * @param bucket - 自建桶名;仅接受可安全用于 S3 路径与 Nginx location 的 DNS 桶名。\n * @param reservedPaths - 应用目录和 API 前缀,桶路径不能遮蔽其中任一路由。\n * @param storageBasePath - 已校验的公开入口目录,空字符串保持根桶路径。\n * @returns 不含凭据、不记录签名查询的 location 片段。\n * @example 模块内部上下文\n * ```ts\n * const route = renderStorageLocation('uploads', ['/api/v1', '/portal'])\n * void route\n * ```\n */\nfunction renderStorageLocation(bucket: string, reservedPaths: string[], storageBasePath = ''): string {\n // 与网站目录共用安全路径校验;入口可位于网站目录内,但不能覆盖 API、资源或健康接口。\n renderWebLocation(storageBasePath)\n const path = `${storageBasePath}/${bucket}`\n const reserved = ['/health', '/_hai', ...reservedPaths].filter(Boolean)\n if (!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(bucket) || bucket.includes('..')\n || ['health', '_hai'].includes(bucket)\n || reserved.some(item => item === path || item.startsWith(`${path}/`) || path.startsWith(`${item}/`)\n || (storageBasePath && (item === storageBasePath || item.startsWith(`${storageBasePath}/`) || storageBasePath.startsWith(`${item}/`))))) {\n throw new Error('Storage bucket conflicts with application routes or is not a valid DNS bucket name')\n }\n return ` location ^~ ${path}/ {\n # 预签名 URL 属于短期访问凭据,不写入代理访问或错误日志。\n access_log off;\n error_log /dev/null;\n # 对象可能含不可信 HTML;同源下载也不能取得应用脚本权限或泄露签名来源。\n add_header Content-Security-Policy \"sandbox; default-src 'none'; base-uri 'none'; form-action 'none'\" always;\n proxy_hide_header X-Content-Type-Options;\n add_header X-Content-Type-Options nosniff always;\n proxy_hide_header Referrer-Policy;\n add_header Referrer-Policy no-referrer always;\n proxy_hide_header Cache-Control;\n add_header Cache-Control \"private, no-store\" always;\n limit_except GET PUT OPTIONS { deny all; }\n client_max_body_size 0;\n${storageBasePath\n ? ` # map 保留原始 URI 与查询;不在 location 内创建改变代理继承的 if 配置。\n proxy_pass http://hai_storage_proxy$hai_storage_uri;`\n : ' proxy_pass http://storage:9000;'}\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header Connection \"\";\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_connect_timeout 5s;\n proxy_read_timeout 300s;\n proxy_send_timeout 300s;\n }\n`\n}\n\n/**\n * 显式 upstream 允许带原始 URI 变量转发,避免依赖不同容器引擎的运行时 DNS resolver。\n * @param bucket - 已由对象路由校验的自建桶名。\n * @param storageBasePath - 安全入口目录,空字符串无需 URI 映射。\n * @returns 位于 http 上下文的 upstream 与 map,保留编码和查询并移除入口目录。\n * @example 模块内部上下文\n * ```ts\n * const config = renderStorageUpstream('business-files', '/delivery/files')\n * void config\n * ```\n */\nfunction renderStorageUpstream(bucket: string, storageBasePath = ''): string {\n if (!storageBasePath)\n return ''\n const path = `${storageBasePath}/${bucket}`.replaceAll('.', '\\\\\\\\.')\n return `upstream hai_storage_proxy { server storage:9000; }\nmap $request_uri $hai_storage_uri {\n default $request_uri;\n \"~^${path}(/.*)$\" /${bucket}$1;\n}\n`\n}\n\n/**\n * 为独立 API 或 SvelteKit SSR 生成对象存储网关,应用路径(含部署目录)原样转发。\n * @param options - 内部服务、端口、桶、保留路径、transport 容量和上游代理 IP/CIDR。\n * @param options.primaryService - 实际处理请求的应用服务。\n * @param options.port - 应用容器内端口。\n * @param options.bucket - 私有 S3 桶名。\n * @param options.storageBasePath - publicEndpoint 中的代理目录,不包含桶名。\n * @param options.reservedPaths - 不能与桶路由重叠的应用路径。\n * @param options.maxPlaintextBytes - 应用 transport 明文预算。\n * @param options.trustedEdgeProxies - Nginx 上游可信负载均衡 IP/CIDR。\n * @returns 监听 8080 的公开 Nginx 配置,不含应用或对象存储凭据。\n * @example 模块内部上下文\n * ```ts\n * const config = generateApplicationProxyConfig({ primaryService: 'web', port: 3000, bucket: 'uploads', reservedPaths: ['/portal'] })\n * void config\n * ```\n */\nexport function generateApplicationProxyConfig(options: { primaryService: 'serv' | 'web', port: number, bucket?: string, reservedPaths: string[], storageBasePath?: string, maxPlaintextBytes?: number, trustedEdgeProxies?: string[] }): string {\n const { primaryService, port, bucket, reservedPaths, maxPlaintextBytes } = options\n if (!Number.isInteger(port) || port < 1 || port > 65535)\n throw new Error('Invalid application proxy target')\n const bodyLimits = resolveTransportBodyLimits(maxPlaintextBytes)\n return `${bucket ? renderStorageUpstream(bucket, options.storageBasePath) : ''}server {\n listen 8080;\n server_name _;\n${renderTrustedEdgeProxies(options.trustedEdgeProxies)} large_client_header_buffers 4 32k;\n${bucket ? renderStorageLocation(bucket, reservedPaths, options.storageBasePath) : ''} location = /_hai/gateway-health {\n access_log off;\n return 200 'ok';\n }\n location / {\n client_max_body_size ${bodyLimits.encryptedPayloadBytes};\n proxy_pass http://${primaryService}:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header Connection \"\";\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_buffer_size 32k;\n proxy_buffers 8 32k;\n }\n}\n`\n}\n\n/** 上游 LB 只接受显式 IP/CIDR;随后用 Nginx 已验证的 remote_addr 重写转发头。 */\nfunction renderTrustedEdgeProxies(entries: string[] = []): string {\n if (!TrustedProxiesSchema.safeParse(entries).success)\n throw new Error('Invalid trusted edge proxy address')\n if (!entries.length)\n return ''\n return `${entries.map(entry => ` set_real_ip_from ${entry};`).join('\\n')}\\n real_ip_header X-Forwarded-For;\\n real_ip_recursive on;\\n`\n}\n\n/**\n * 目录路由共享同一校验与静态回退;文件命中后直接输出,避免重定向到域名根目录。\n * @param webBasePath - 无末尾斜杠的目录,空字符串为根目录。\n * @returns 包含目录校验、无末尾斜杠跳转和静态回退的 location 配置。\n * @example 模块内部上下文\n * ```ts\n * const locations = renderWebLocation('/portal')\n * void locations\n * ```\n */\nfunction renderWebLocation(webBasePath: string): string {\n if (webBasePath && (!/^\\/[\\w.-]+(?:\\/[\\w.-]+)*$/.test(webBasePath) || webBasePath.split('/').some(segment => segment === '.' || segment === '..') || ['/health', '/_hai/web-health'].includes(webBasePath)))\n throw new Error('Invalid web base path')\n return webBasePath\n ? ` absolute_redirect off;\n location = ${webBasePath} {\n return 308 ${webBasePath}/$is_args$args;\n }\n location ${webBasePath}/ {\n rewrite ^${webBasePath.replaceAll('.', '\\\\.').replaceAll('-', '\\\\-')}/(.*)$ /$1 break;\n try_files $uri/index.html $uri /index.html =404;\n }\n location / { return 404; }\n`\n : ` location / {\n try_files $uri $uri/ /index.html;\n }\n`\n}\n\n/**\n * 独立Vite站点复用目录路由,公开运行配置仍由已有启动脚本生成,保留外部API地址与品牌字段。\n * @param port - Web容器实际监听端口。\n * @param webBasePath - 已声明的Web挂载目录;无末尾斜杠,空字符串表示根目录。\n * @returns 只含静态页面、公开运行配置和健康入口的Nginx配置。\n * @example 模块内部上下文\n * ```ts\n * const config = generateStaticWebConfig(8080, '/portal')\n * void config\n * ```\n */\nexport function generateStaticWebConfig(port: number, webBasePath: string): string {\n if (!Number.isInteger(port) || port < 1 || port > 65535)\n throw new Error('Invalid web proxy target')\n return `server {\n listen ${port};\n server_name _;\n root /usr/share/nginx/html;\n${renderWebLocation(webBasePath)} location = ${webBasePath}/runtime-config.js {\n alias /tmp/hai-runtime-config/runtime-config.js;\n add_header Cache-Control \"no-store\";\n default_type application/javascript;\n }\n location = /health {\n access_log off;\n return 200 'ok';\n }\n}\n`\n}\n\n/**\n * 将环境变量对象序列化为 .env.runtime 内容(每行 KEY=VALUE)。\n * 编码 dotenv 值,不进行脱敏;含密钥时只能写入受保护的运行环境文件。\n * @param env - 要序列化的运行变量,可能包含秘密。\n * @param overrides - 后加载的运行变量;被其覆盖的项不重复写入本文件。\n * @returns 保留字面量值且正确转义的 dotenv 文本,不进行脱敏。\n * @example 模块内部上下文\n * ```ts\n * const content = serializeEnvFile({ NODE_ENV: 'production', HAI_CORE_NAME: 'Shop app' })\n * ```\n */\nexport function serializeEnvFile(env: Record<string, string>, overrides: Record<string, string> = {}): string {\n // 与运行时保持一致:后加载文件的同名项及 HAI 父对象都会遮蔽子项。\n const effective = { ...env, ...overrides }\n return `${Object.entries(env)\n .filter(([name]) => {\n if (Object.hasOwn(overrides, name))\n return false\n if (!name.startsWith('HAI_') || PROCESS_ENV_KEYS.has(name) || name.startsWith('HAI_E2E_'))\n return true\n for (let at = name.indexOf('_', 4); at !== -1; at = name.indexOf('_', at + 1)) {\n if (Object.hasOwn(effective, name.slice(0, at)))\n return false\n }\n return true\n })\n .map(([key, value]) => {\n let literal = value\n if (/[\\s#$'\"]/.test(value)) {\n if (value.startsWith('{') || value.startsWith('['))\n literal = `'${value.replaceAll('\\'', '\\\\u0027')}'`\n else if (!value.includes('\\''))\n literal = `'${value}'`\n else\n literal = JSON.stringify(value).replaceAll('$', '$$')\n }\n return `${key}=${literal}`\n })\n .join('\\n')}\\n`\n}\n","/**\n * @h-ai/deploy — docker-ssh 部署 Provider\n *\n * 基于 OCI 镜像 + Docker Compose + SSH 的通用主机部署:消费已有镜像 → tar 打包 → SSH 传输 →\n * 远程 load → compose up → HTTP 健康检查。远程需 SSH、Linux flock/基础工具及 docker/podman + compose。\n * @module deploy-provider-docker-ssh\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n ContainerDeployContext,\n ContainerDeployProvider,\n ContainerRuntime,\n} from '../container/deploy-container-types.js'\nimport type { DeployConfig, DockerSshProviderConfig } from '../deploy-config.js'\nimport type { DeployResult } from '../deploy-types.js'\nimport { createHash, randomBytes } from 'node:crypto'\nimport { chmodSync, existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { request as requestHttps } from 'node:https'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { rootCertificates } from 'node:tls'\nimport { parseEnv } from 'node:util'\nimport { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'\nimport { core, CoreConfigSchema, err, ok, RequestAccessConfigSchema } from '@h-ai/core'\nimport { createTransportBodyPolicy, parseTransportServerKeyRing, resolveTransportBodyLimits } from '@h-ai/crypto'\nimport { stringify } from 'yaml'\nimport { z } from 'zod'\nimport { createDeploymentBundle } from '../container/deploy-bundle.js'\nimport { maskSecrets } from '../container/deploy-command.js'\nimport {\n buildRuntimeEnv,\n generateApplicationProxyConfig,\n generateComposeFile,\n generateStaticWebConfig,\n generateWebProxyConfig,\n serializeEnvFile,\n} from '../container/deploy-container-compose.js'\nimport { createHttpsAssets, renderHttpsProxy } from '../container/deploy-https.js'\nimport { shellArgument } from '../container/deploy-scripts.js'\nimport { createSshExecutor } from '../container/deploy-ssh.js'\nimport { describeDeploymentVariableSources, loadDeploymentConfig, loadDeploymentEnvironment, saveDeploymentEnvironment } from '../deploy-environment.js'\nimport { resolveProjectDirectory } from '../deploy-functions.js'\nimport { deployM } from '../deploy-i18n.js'\nimport { getDeployCommandState } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provider-docker-ssh' })\n\n/** 健康检查轮询间隔(毫秒) */\nconst HEALTH_POLL_INTERVAL = 3000\n\n/** 只处理本次选中的应用配置;文件按应用目录读取,运行期路径不回写调用方环境。 */\nfunction prepareRequestAccess(options: { settings: Record<string, unknown>, module: 'serv' | 'kit', directory: string }): HaiResult<{ settings: Record<string, unknown>, snapshot?: string }> {\n const scope = options.module === 'serv' ? options.settings.http : options.settings\n if (!scope || typeof scope !== 'object' || !('access' in scope))\n return ok({ settings: options.settings })\n const configured = RequestAccessConfigSchema.safeParse(scope.access)\n if (!configured.success)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_requestAccessInvalid', { params: { field: options.module === 'serv' ? 'serv.http.access' : 'kit.access' } }))\n try {\n const policy = core.access.loadPolicy(configured.data, options.directory)\n const check = core.access.createRequestCheck(policy)\n if (check.requiresEncryption && !options.settings.transport)\n throw new Error('Transport encryption is required but not configured')\n if (configured.data === false || !('file' in configured.data))\n return ok({ settings: options.settings })\n const access = { file: '/run/hai/request-access.yml' }\n const settings = options.module === 'serv'\n ? { ...options.settings, http: { ...scope, access } }\n : { ...options.settings, access }\n return ok({ settings, snapshot: stringify(policy, { aliasDuplicateObjects: false }) })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_requestAccessInvalid', { params: { field: options.module === 'serv' ? 'serv.http.access' : 'kit.access' } }))\n }\n}\n\n/** 健康检查最大轮询次数 */\nconst HEALTH_MAX_ATTEMPTS = 40\n\n/** 只提取 Serv 已注册的精确路径;阻止配置路径进入 Nginx 指令或 shell 语法。 */\nfunction servicePath(value: unknown, fallback: string): string {\n const path = value ?? fallback\n if (typeof path !== 'string' || !/^\\/[\\w./-]*$/.test(path) || path.includes('//') || path.split('/').some(part => part === '.' || part === '..'))\n throw new Error('Invalid service endpoint path')\n return path\n}\n\n/** 未配置的健康检查沿用 Serv 默认;文档必须显式使用对象启用。 */\nfunction endpointSettings(value: unknown): Record<string, unknown> {\n if (value === undefined)\n return {}\n if (!value || typeof value !== 'object' || Array.isArray(value))\n throw new Error('Invalid service endpoint configuration')\n return value as Record<string, unknown>\n}\n\n/** 只接收服务器脚本原子发布的终态;匹配 ID 后才能确认本次执行完成。 */\nconst ServerResultSchema = z.object({\n deploymentId: z.string(),\n stage: z.enum(['preflight', 'credentials', 'recover', 'images', 'dependencies', 'start', 'https', 'health', 'complete']),\n exitCode: z.number().int().min(0).max(255),\n durationSeconds: z.number().int().nonnegative(),\n recoveryStatus: z.enum(['not-needed', 'passed', 'failed', 'stopped']).optional(),\n})\n\n/** 生成不可变部署 ID:`YYYYMMDD-HHmmss-<random>`。 */\nfunction makeDeploymentId(): string {\n const now = new Date()\n const pad = (n: number): string => String(n).padStart(2, '0')\n const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`\n + `-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`\n return `${stamp}-${randomBytes(3).toString('hex')}`\n}\n\n/** 睡眠指定毫秒。 */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/**\n * 创建 docker-ssh 部署 Provider。\n * @param config - docker-ssh Provider 配置\n * @param container - Compose 中间件参数\n * @returns 容器部署 Provider 实例\n * @example 模块内部上下文\n * ```ts\n * const provider = createDockerSshProvider({ type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } })\n * const name = provider.name // 创建本身不连接 SSH;在线发布仍需有效 SSH 配置。\n * ```\n */\nexport function createDockerSshProvider(\n config: DockerSshProviderConfig,\n container?: DeployConfig['container'],\n): ContainerDeployProvider {\n const ssh = config.ssh ? createSshExecutor(config.ssh) : undefined\n const baseDir = config.remote.baseDir\n\n /** 探测远程容器运行时与 compose 可用性。 */\n async function detectRemoteRuntime(): Promise<HaiResult<ContainerRuntime>> {\n if (!ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n const candidates: ContainerRuntime[] = config.remote.runtime === 'auto'\n ? ['podman', 'docker']\n : [config.remote.runtime]\n\n for (const runtime of candidates) {\n const versionResult = await ssh.exec(`${runtime} version`, { timeoutMs: 20_000 })\n if (!versionResult.success)\n continue\n const composeResult = await ssh.exec(`${runtime} compose version`, { timeoutMs: 20_000 })\n if (composeResult.success) {\n logger.info('Remote container runtime detected', { runtime })\n return ok(runtime)\n }\n }\n return err(\n HaiDeployError.REMOTE_COMMAND_FAILED,\n deployM('deploy_remoteRuntimeMissing', { params: { runtime: candidates.join(' / ') } }),\n )\n }\n\n /** HTTP 健康检查:轮询访问地址直到返回成功。 */\n async function healthCheck(url: string, certificate?: string): Promise<boolean> {\n for (let attempt = 0; attempt < HEALTH_MAX_ATTEMPTS; attempt++) {\n try {\n if (certificate) {\n const healthy = await new Promise<boolean>((resolve) => {\n const request = requestHttps(url, { ca: [...rootCertificates, certificate], timeout: 5000 }, (response) => {\n response.resume()\n resolve(response.statusCode !== undefined && response.statusCode >= 200 && response.statusCode < 300)\n })\n request.on('error', () => resolve(false))\n request.on('close', () => resolve(false))\n request.on('timeout', () => request.destroy())\n request.end()\n })\n if (healthy)\n return true\n }\n else {\n const response = await fetch(url, { signal: AbortSignal.timeout(5000) })\n // 健康检查只消费状态码,主动释放响应体和连接,避免失败轮询积压未读数据。\n await response.body?.cancel()\n if (response.ok)\n return true\n }\n }\n catch {\n // 未就绪,继续轮询\n }\n await sleep(HEALTH_POLL_INTERVAL)\n }\n return false\n }\n\n const deploy = async (context: ContainerDeployContext): Promise<HaiResult<DeployResult>> => {\n const { appDir, projectName, scan, provisionEnv, appEnv, options } = context\n const deploymentId = makeDeploymentId()\n const hostPort = config.expose.hostPort\n const https = config.expose.https\n const httpsAssets = https ? createHttpsAssets(https, resolveProjectDirectory(appDir)) : undefined\n const deploymentRoot = join(resolveProjectDirectory(appDir), '.hai', 'deploy', options?.environment ?? 'prod')\n const artifact = context.artifact\n const resolvedBuildDir = context.artifactDir\n const images = artifact.images\n const web = images.find(image => image.name === 'web')\n const primaryService = artifact.primaryService\n const app = images.find(image => image.name === primaryService)\n if (options?.selectedServices) {\n const available: string[] = [...images.map(image => image.name), ...scan.requiredServices]\n const invalid = options.selectedServices.find(name => !available.includes(name))\n if (!options.selectedServices.length || new Set(options.selectedServices).size !== options.selectedServices.length || invalid)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: invalid ?? options.selectedServices.join(', ') } }))\n }\n const hasWebProxy = primaryService === 'serv' && artifact.hasWeb\n const partial = artifact.partial || options?.selectedServices !== undefined\n const containerPort = app?.containerPort ?? (primaryService === 'serv' ? artifact.servContainerPort : artifact.webContainerPort) ?? config.expose.containerPort\n const webContainerPort = web?.containerPort ?? artifact.webContainerPort ?? 8080\n const host = config.ssh?.host\n const url = https ? `https://${https.domain}${https.port === 443 ? '' : `:${https.port}`}` : host ? `http://${host.includes(':') ? `[${host}]` : host}:${hostPort}` : `http://SERVER_HOST:${hostPort}`\n const webBasePath = artifact.webBasePath ?? ''\n const applicationUrl = `${url}${webBasePath ? `${webBasePath}/` : ''}`\n const standaloneWebConfig = primaryService === 'web' && !scan.isSvelteKit && (!!webBasePath || !!https)\n const healthPaths = hasWebProxy ? ['/_hai/web-health', `${webBasePath}/`] : scan.isSvelteKit ? [`${webBasePath}/`] : primaryService === 'serv' ? [] : standaloneWebConfig ? ['/health', `${webBasePath}/`] : ['/health']\n\n // 先保存开通结果和 sidecar 凭据,传输失败后仍可检查与复用配置。\n const { env, sidecar } = buildRuntimeEnv(appDir, projectName, scan, provisionEnv, containerPort, options, appEnv, container?.s3Engine)\n if (https && scan.isSvelteKit && !env.ORIGIN)\n env.ORIGIN = url\n const managedStorage = sidecar.services.includes('storage') ? JSON.parse(sidecar.env.HAI_STORAGE) as { bucket: string, secretAccessKey: string, publicEndpoint?: unknown } : undefined\n let storageBasePath = ''\n if (managedStorage?.publicEndpoint !== undefined) {\n // 与 Storage 的公开端点约束一致,在归档/上传前报告错误,不输出配置中的 URL 或秘密。\n try {\n if (typeof managedStorage.publicEndpoint !== 'string')\n throw new Error('Invalid public endpoint type')\n // eslint-disable-next-line no-control-regex -- 在 URL 标准化前拒绝控制字符及编码目录。\n const unsafeCharacters = /[\\u0000-\\u0020\\u007F\\\\%]/.test(managedStorage.publicEndpoint)\n const endpoint = new URL(managedStorage.publicEndpoint)\n if (!['http:', 'https:'].includes(endpoint.protocol) || endpoint.username || endpoint.password || endpoint.search || endpoint.hash\n || !/^\\/(?:[\\w.-]+(?:\\/[\\w.-]+)*\\/?)?$/.test(endpoint.pathname)\n || unsafeCharacters || /(?:^|\\/)\\.{1,2}(?:\\/|$)/.test(managedStorage.publicEndpoint)) {\n throw new Error('Invalid public endpoint origin')\n }\n storageBasePath = endpoint.pathname.replace(/\\/+$/, '')\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storagePublicEndpointInvalid'))\n }\n }\n // 应用增量继承已安装连接配置;对外地址或桶等配置改变须全量切换,不能静默沿用旧值。\n const storageRouting = managedStorage ? createHash('sha256').update(JSON.stringify({ ...managedStorage, secretAccessKey: undefined })).digest('hex') : ''\n // SSR/API 没有现成 Web Nginx 时追加网关;静态客户端不能持有存储服务端凭据。\n const gateway = !hasWebProxy && (!!managedStorage || (!!https && !standaloneWebConfig))\n if (gateway && primaryService === 'web' && !scan.isSvelteKit)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageBackendRequired'))\n const proxyService = gateway ? 'gateway' : 'web'\n if (gateway)\n healthPaths.push('/_hai/gateway-health')\n const updatesApp = options?.selectedServices ? options.selectedServices.includes(primaryService) : !!app\n const serverPath = join(appDir, 'config', '_serv.yml')\n const server = existsSync(serverPath) || hasWebProxy ? loadDeploymentConfig('serv', serverPath, env) : ok<Record<string, unknown>>({})\n if (!server.success)\n return server\n const backendPaths: string[] = []\n try {\n const http = endpointSettings(server.data.http)\n if (primaryService === 'serv' && http.health !== false) {\n const health = endpointSettings(http.health)\n const path = servicePath(health.path, '/health')\n healthPaths.unshift(path)\n backendPaths.push(path, servicePath(health.readyPath, '/ready'))\n }\n if (hasWebProxy) {\n // 生成应用按 Core 环境关闭生产文档,不能用部署目标名或 NODE_ENV 猜测启用状态。\n const corePath = join(appDir, 'config', '_core.yml')\n const settings = existsSync(corePath) ? loadDeploymentConfig('core', corePath, env) : ok(env.HAI_CORE ? JSON.parse(env.HAI_CORE) : { env: env.HAI_CORE_ENV })\n if (!settings.success)\n return settings\n const application = CoreConfigSchema.safeParse(settings.data)\n if (!application.success)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n if (application.data.env !== 'production') {\n if (http.openapi !== undefined && http.openapi !== false)\n backendPaths.push(servicePath(endpointSettings(http.openapi).path, '/openapi.json'))\n if (http.docs !== undefined && http.docs !== false) {\n const docsPath = servicePath(endpointSettings(http.docs).path, '/docs')\n backendPaths.push(docsPath, `${docsPath.slice(0, docsPath.lastIndexOf('/') + 1)}_hai/scalar.js`)\n }\n }\n }\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n }\n let requestAccessSnapshot: string | undefined\n if (updatesApp && primaryService === 'serv') {\n const prepared = prepareRequestAccess({ settings: server.data, module: 'serv', directory: appDir })\n if (!prepared.success)\n return prepared\n Object.assign(server.data, prepared.data.settings)\n requestAccessSnapshot = prepared.data.snapshot\n if (requestAccessSnapshot)\n env.HAI_SERV = JSON.stringify(server.data)\n }\n let feedbackTransportBytes: number | undefined\n if (scan.haiModules?.includes('@h-ai/feedback')) {\n const policy = loadDeploymentConfig('feedback', join(appDir, 'config', '_feedback.yml'), env)\n if (!policy.success)\n return policy\n try {\n feedbackTransportBytes = resolveFeedbackBudget(policy.data).maxTransportBytes\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_transportBodyLimitInvalid'))\n }\n }\n let protectedTransport = !!server.data.transport\n let applicationPlaintextBytes: number | undefined\n if (scan.isSvelteKit) {\n const kitPath = join(appDir, 'config', '_kit.yml')\n const kit = existsSync(kitPath) ? loadDeploymentConfig('kit', kitPath, env) : ok({})\n if (!kit.success)\n return kit\n if (updatesApp) {\n const prepared = prepareRequestAccess({ settings: kit.data, module: 'kit', directory: appDir })\n if (!prepared.success)\n return prepared\n Object.assign(kit.data, prepared.data.settings)\n requestAccessSnapshot = prepared.data.snapshot\n if (requestAccessSnapshot)\n env.HAI_KIT = JSON.stringify(kit.data)\n }\n const transport = (kit.data as Record<string, unknown>).transport\n if (transport && typeof transport === 'object') {\n protectedTransport = !('enabled' in transport) || transport.enabled !== false\n try {\n const configured = (transport as { maxPlaintextBytes?: number | 'auto' }).maxPlaintextBytes\n const routes = (transport as { routePlaintextBytes?: Record<string, number> }).routePlaintextBytes\n const limits = resolveTransportBodyLimits(Math.max(createTransportBodyPolicy(configured === 'auto' ? undefined : configured, routes).maximum.plaintextBytes, feedbackTransportBytes ?? 0))\n // adapter-node 默认容量比 transport 小;正式部署必须使用同一派生密文预算。\n env.BODY_SIZE_LIMIT = String(limits.encryptedPayloadBytes)\n applicationPlaintextBytes = limits.plaintextBytes\n }\n catch (error) {\n return err(HaiDeployError.CONFIG_ERROR, error instanceof RangeError ? error.message : deployM('deploy_transportBodyLimitInvalid'))\n }\n }\n }\n if (updatesApp && protectedTransport && scan.haiModules?.includes('@h-ai/crypto') && !parseTransportServerKeyRing(env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING).success)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_transportKeyRingInvalid', { params: { path: join(scan.envDir ?? appDir, `.env.${options?.environment ?? 'prod'}.local`) } }))\n let webProxy: string | undefined\n if (hasWebProxy) {\n // 路由取当前服务的真实配置,不扫描相邻应用或猜测 fullstack 布局。\n const http = server.data.http as { apiPrefix?: string } | undefined\n const cors = server.data.cors as { origin?: string } | undefined\n const apiPrefix = http?.apiPrefix ?? '/api/v1'\n if (typeof apiPrefix !== 'string' || !/^\\/[\\w.-]+(?:\\/[\\w.-]+)*$/.test(apiPrefix) || apiPrefix.split('/').some(part => part === '.' || part === '..')) {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n }\n if (webBasePath && ([...backendPaths, '/_hai/web-health'].includes(webBasePath) || webBasePath === apiPrefix.replace(/\\/+$/, '') || webBasePath.startsWith(`${apiPrefix.replace(/\\/+$/, '')}/`)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webBaseConflict'))\n const transport = server.data.transport as { maxPlaintextBytes?: number | 'auto', routePlaintextBytes?: Record<string, number> } | false | undefined\n try {\n const configured = transport ? transport.maxPlaintextBytes : undefined\n const limits = resolveTransportBodyLimits(Math.max(createTransportBodyPolicy(configured === 'auto' ? undefined : configured, transport ? transport.routePlaintextBytes : undefined).maximum.plaintextBytes, feedbackTransportBytes ?? 0))\n webProxy = generateWebProxyConfig(containerPort, apiPrefix, { webPort: webContainerPort, maxPlaintextBytes: limits.plaintextBytes, webBasePath, backendPaths, storageBucket: managedStorage?.bucket, storageBasePath, trustedEdgeProxies: config.trustedEdgeProxies })\n }\n catch (error) {\n return err(HaiDeployError.CONFIG_ERROR, error instanceof RangeError ? error.message : deployM(managedStorage ? 'deploy_storageProxyInvalid' : 'deploy_transportBodyLimitInvalid'))\n }\n // 每次从当前配置生成,避免上次运行环境里的父对象遮蔽新修改;保留明确 Origin。\n env.HAI_SERV = JSON.stringify({ ...server.data, cors: { ...cors, origin: (!cors?.origin || cors.origin === '*') && (config.ssh || https) ? url : cors?.origin ?? '*' } })\n }\n else if (gateway) {\n try {\n const http = server.data.http as { apiPrefix?: string } | undefined\n if (primaryService === 'serv') {\n const transport = server.data.transport as { maxPlaintextBytes?: number | 'auto', routePlaintextBytes?: Record<string, number> } | undefined\n applicationPlaintextBytes = Math.max(createTransportBodyPolicy(transport?.maxPlaintextBytes === 'auto' ? undefined : transport?.maxPlaintextBytes, transport?.routePlaintextBytes).maximum.plaintextBytes, feedbackTransportBytes ?? 0)\n }\n webProxy = generateApplicationProxyConfig({ primaryService, port: containerPort, bucket: managedStorage?.bucket, storageBasePath, reservedPaths: [http?.apiPrefix ?? '/api/v1', ...(storageBasePath ? [`${webBasePath}/_app`, `${webBasePath}/assets`, `${webBasePath}/runtime-config.js`] : [webBasePath])], maxPlaintextBytes: applicationPlaintextBytes, trustedEdgeProxies: config.trustedEdgeProxies })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageProxyInvalid'))\n }\n }\n else if (standaloneWebConfig) {\n if (['/health', '/_hai/web-health'].includes(webBasePath))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webBaseConflict'))\n webProxy = generateStaticWebConfig(containerPort, webBasePath)\n }\n if (https && webProxy)\n webProxy = renderHttpsProxy(webProxy, https, hasWebProxy ? webContainerPort : gateway ? 8080 : containerPort)\n if (https && primaryService === 'serv' && !hasWebProxy) {\n const cors = server.data.cors as { origin?: string } | undefined\n env.HAI_SERV = JSON.stringify({ ...server.data, cors: { ...cors, origin: !cors?.origin || cors.origin === '*' ? url : cors.origin } })\n }\n // 一次交付对应一个目录;自定义同名输出也不覆盖已经可复制的旧包。\n const requestedOutput = options?.output ?? join(deploymentRoot, `bundle-${projectName}-${deploymentId}-${artifact.appVersion}.tar.gz`)\n const compressed = requestedOutput.endsWith('.tar.gz')\n const stem = basename(requestedOutput).replace(/\\.tar(?:\\.gz)?$/i, '')\n const suffix = `-${artifact.appVersion}`\n const name = stem.endsWith(suffix) ? stem : `${stem}${suffix}`\n if (!/^[\\w.+-]+$/.test(name))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleNameInvalid'))\n const artifactDir = resolve(dirname(requestedOutput), name)\n if (existsSync(artifactDir))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleDirectoryExists', { params: { path: artifactDir } }))\n mkdirSync(dirname(artifactDir), { recursive: true, mode: 0o700 })\n mkdirSync(artifactDir, { mode: 0o700 })\n chmodSync(artifactDir, 0o700)\n const envPath = join(artifactDir, '.env.runtime')\n const nodeRuntime = primaryService === 'serv' || scan.isSvelteKit\n const startupOverrides: Record<string, string> = nodeRuntime ? { NODE_OPTIONS: '', HAI_DEPLOY_PRIVATE_PROXY: '' } : {}\n const runtimeEnvironment = serializeEnvFile(env, { ...sidecar.env, ...startupOverrides })\n const middlewareEnv = serializeEnvFile(sidecar.env, Object.fromEntries(Object.entries(env).filter(([name]) => !Object.hasOwn(sidecar.env, name))))\n const envVarsSet = [...new Set([\n ...Object.keys(parseEnv(runtimeEnvironment)),\n ...Object.keys(parseEnv(middlewareEnv)),\n ...(nodeRuntime ? ['NODE_OPTIONS'] : []),\n ...(hasWebProxy || gateway ? ['HAI_DEPLOY_PRIVATE_PROXY'] : []),\n ])]\n writeFileSync(envPath, runtimeEnvironment, { mode: 0o600 })\n if (requestAccessSnapshot)\n writeFileSync(join(artifactDir, 'request-access.yml'), requestAccessSnapshot, { mode: 0o600 })\n writeFileSync(join(artifactDir, 'middleware-runtime.env'), serializeEnvFile(sidecar.containerEnv), { mode: 0o600 })\n if (options?.environment) {\n const environment = loadDeploymentEnvironment({ environment: options.environment, envDir: options.envDir ?? scan.envDir ?? appDir })\n if (!environment.success)\n return environment\n const saved = saveDeploymentEnvironment(environment.data, { HAI_DEPLOY_ENVIRONMENT: environment.data.environment, HAI_CORE_ENV: environment.data.values.HAI_CORE_ENV, ...sidecar.env, ...provisionEnv })\n if (!saved.success)\n return saved\n }\n\n const composeName = `docker-compose-${artifact.appVersion}.yml`\n const composeContent = generateComposeFile({\n projectName,\n appVersion: artifact.appVersion,\n imageRef: app?.imageRef ?? 'localhost/hai-unselected:0',\n hostPort,\n containerPort,\n primaryService,\n requestAccessPolicy: requestAccessSnapshot !== undefined,\n nodeRuntime,\n nodeOptions: env.NODE_OPTIONS,\n sidecar,\n web: hasWebProxy ? { imageRef: web?.imageRef ?? 'localhost/hai-unselected:0', containerPort: webContainerPort } : undefined,\n mountWebConfig: standaloneWebConfig,\n gateway,\n https,\n })\n const composePath = join(artifactDir, composeName)\n writeFileSync(composePath, composeContent)\n if (webProxy)\n writeFileSync(join(artifactDir, 'web.conf'), webProxy)\n const selected = options?.selectedServices ? [...options.selectedServices] : artifact.partial ? images.map(image => image.name) : [...images.map(image => image.name), ...Object.keys(sidecar.composeServices)]\n if (gateway && !partial)\n selected.push('gateway')\n if (https?.type === 'letsencrypt' && !partial)\n selected.push('certbot')\n if (!selected.length || selected.some(name => !/^[a-z][a-z0-9-]*$/.test(name)) || new Set(selected).size !== selected.length)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: selected.join(', ') } }))\n for (const name of selected) {\n if (['serv', 'web'].includes(name) && !images.some(image => image.name === name))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: name } }))\n }\n options?.onProgress?.('packaging')\n const bundle = await createDeploymentBundle({\n directory: artifactDir,\n artifactDir: resolvedBuildDir,\n artifact,\n projectName,\n environment: options?.environment ?? 'prod',\n deploymentId,\n config,\n runtime: options?.runtime ?? 'auto',\n selected,\n partial,\n hasWebConfig: !!webProxy,\n proxyService,\n storageRouting,\n containerPort,\n middlewareEnv,\n accountSources: describeDeploymentVariableSources(options?.envDir ?? scan.envDir ?? appDir, options?.environment ?? 'prod', env, ['HAI_ADMIN_DEFAULT_PASSWORD', 'HAI_AUDIT_ADMIN_PASSWORD', 'HAI_CONFIG_ADMIN_PASSWORD', 'HAI_BUSINESS_OPERATOR_PASSWORD']),\n healthPaths,\n httpsAssets,\n output: join(artifactDir, `${name}.tar${compressed ? '.gz' : ''}`),\n cacheDirectory: join(resolveProjectDirectory(appDir), '.hai', 'cache', 'images'),\n })\n if (options?.bundleOnly)\n return ok({ url: '', deploymentId, status: 'packaged', provider: 'docker-ssh', healthCheck: 'skipped', envVarsSet, ...bundle })\n if (!ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n const ping = await ssh.ping()\n if (!ping.success)\n return ping\n const remoteRuntime = await detectRemoteRuntime()\n if (!remoteRuntime.success)\n return remoteRuntime\n const remoteDir = `${baseDir}/${projectName}`\n const remoteTar = `${remoteDir}/incoming/${basename(bundle.bundlePath)}`\n const prepared = await ssh.exec(`mkdir -p -- ${shellArgument(`${remoteDir}/incoming`)} && chmod 700 -- ${shellArgument(remoteDir)} ${shellArgument(`${remoteDir}/incoming`)}`)\n if (!prepared.success)\n return prepared\n const uploaded = await ssh.upload(bundle.bundlePath, remoteTar)\n if (!uploaded.success)\n return uploaded\n let pendingOutput = ''\n const started = await ssh.exec(\n `mkdir -p ${shellArgument(`${remoteTar}.contents`)} && chmod 600 ${shellArgument(remoteTar)} && tar -xf ${shellArgument(remoteTar)} -C ${shellArgument(`${remoteTar}.contents`)} && sh ${shellArgument(`${remoteTar}.contents/${bundle.startName}`)} ${shellArgument(remoteDir)} && { rm -rf -- ${shellArgument(`${remoteTar}.contents`)} && rm -f -- ${shellArgument(remoteTar)} || printf '[WARN] Deployment passed; incoming archive cleanup failed\\\\n' >&2; }`,\n { timeoutMs: 600_000, secrets: sidecar.secrets, onOutput: (output) => {\n const parts = output.split('\\n')\n for (let index = 0; index < parts.length; index++) {\n // 进度仅解析行首标签,不保留无限长的构建日志行。\n pendingOutput += parts[index]!.slice(0, 512 - pendingOutput.length)\n if (index === parts.length - 1)\n break\n const line = pendingOutput\n pendingOutput = ''\n const stage = /^\\[(preflight|images|dependencies|start|https|health|complete)\\]/.exec(line)?.[1]\n if (stage)\n options?.onProgress?.(stage as 'preflight' | 'images' | 'dependencies' | 'start' | 'https' | 'health' | 'complete')\n }\n } },\n )\n if (!started.success) {\n const resultFile = `${remoteDir}/result-${deploymentId}.json`\n const state = getDeployCommandState(started.error)\n // 独立连接只读核对,绝不因超时自动再运行 apply 或无条件恢复容器。\n const checked = await ssh.exec(`if [ -f ${shellArgument(resultFile)} ]; then cat -- ${shellArgument(resultFile)}; fi`, { timeoutMs: 20_000, maxCaptureChars: 8192 })\n let terminal: z.infer<typeof ServerResultSchema> | undefined\n if (checked.success && !checked.data.stdoutTruncated) {\n try {\n const parsed = ServerResultSchema.safeParse(JSON.parse(checked.data.stdout))\n if (parsed.success && parsed.data.deploymentId === deploymentId)\n terminal = parsed.data\n }\n catch {\n // 缺失、损坏、超限或不匹配的记录都不能证明远端已停止。\n }\n }\n return err({ ...started.error, message: `${started.error.message}\\n${terminal ? deployM('deploy_remoteFinished', { params: { stage: terminal.stage, code: String(terminal.exitCode) } }) : deployM('deploy_remoteUnknown')}`, suggestion: terminal ? deployM('deploy_remoteFinished', { params: { stage: terminal.stage, code: String(terminal.exitCode) } }) : deployM('deploy_remoteUnknown'), ext: { ...started.error.ext, commandExecution: {\n ...state,\n reason: state?.reason ?? 'exit',\n localTermination: state?.localTermination ?? 'unknown',\n remoteExecution: terminal ? 'finished' : 'unknown',\n deploymentId,\n resultFile,\n ...(terminal ? { remoteExitCode: terminal.exitCode, remoteStage: terminal.stage, remoteRecovery: terminal.recoveryStatus } : {}),\n } } })\n }\n\n // 在线部署完成后检查实际公开入口。\n logger.info('Running health check', { url: applicationUrl })\n let healthy = true\n for (const healthPath of healthPaths) {\n if (!await healthCheck(`${url}${healthPath}`, httpsAssets?.['tls/fullchain.pem'])) {\n healthy = false\n break\n }\n }\n if (!healthy) {\n return err(\n { ...HaiDeployError.HEALTH_CHECK_FAILED, message: deployM('deploy_healthCheckFailed', { params: { url: applicationUrl } }), ext: { commandExecution: {\n reason: 'exit',\n localTermination: 'confirmed',\n remoteExecution: 'finished',\n deploymentId,\n resultFile: `${remoteDir}/result-${deploymentId}.json`,\n remoteExitCode: 0,\n remoteStage: 'complete',\n remoteRecovery: 'not-needed',\n } } },\n )\n }\n\n const result: DeployResult = {\n url: applicationUrl,\n deploymentId,\n status: 'ready',\n provider: 'docker-ssh',\n healthCheck: 'passed',\n envVarsSet,\n bundlePath: bundle.bundlePath,\n }\n logger.info('docker-ssh deployment complete', { url: applicationUrl, deploymentId })\n return ok(result)\n }\n\n const deploySafely: ContainerDeployProvider['deploy'] = async (context) => {\n try {\n return await deploy(context)\n }\n catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n let safeReason = 'Deployment bundle failed'\n try {\n safeReason = maskSecrets(reason, [...Object.values(context.appEnv ?? {}), config.ssh?.password ?? ''].filter(Boolean))\n }\n catch {\n // 脱敏配置无效时保留固定诊断,不重新暴露原异常。\n }\n logger.error('Deployment bundle failed', { reason: safeReason })\n return err(HaiDeployError.DEPLOY_FAILED, deployM('deploy_bundleFailed', { params: { reason: safeReason } }))\n }\n }\n return { name: 'docker-ssh', deploy: deploySafely }\n}\n","/**\n * @h-ai/deploy — Vercel 部署 Provider\n *\n * 封装 Vercel REST API,实现 DeployProvider 接口。 使用原生 fetch 调用,零外部 SDK 依赖。\n * @module deploy-provider-vercel\n */\n\nimport type { HaiError, HaiErrorDef, HaiResult } from '@h-ai/core'\nimport type { DeployProvider } from '../deploy-internal-types.js'\nimport type { DeployResult } from '../deploy-types.js'\nimport { createHash } from 'node:crypto'\nimport { readdirSync, readFileSync, statSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provider-vercel' })\n\n/** Vercel API 基址 */\nconst VERCEL_API = 'https://api.vercel.com'\n\n/** 部署状态轮询间隔(毫秒) */\nconst POLL_INTERVAL = 3000\n\n/** 部署状态轮询最大次数 */\nconst MAX_POLL_ATTEMPTS = 60\n\n// ─── 内部工具 ───\n\n/** Vercel API 错误,保留状态码用于区分 404 与真实失败 */\nclass VercelApiError extends Error {\n constructor(readonly status: number) {\n super(deployM('deploy_apiError', { params: { service: 'Vercel', status: String(status) } }))\n }\n}\n\n/** 构造标准错误对象 */\nfunction toDeployError(codeDef: HaiErrorDef, messageKey: string, error: unknown): HaiError {\n return {\n ...codeDef,\n message: deployM(messageKey as Parameters<typeof deployM>[0], {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n cause: error,\n }\n}\n\n/**\n * 发送 Vercel API 请求\n *\n * @param token - API Token\n * @param path - API 路径(如 /v2/user)\n * @param options - fetch 选项\n * @returns 解析后的 JSON 响应\n */\nasync function vercelFetch<T>(token: string, path: string, options?: RequestInit): Promise<T> {\n const url = `${VERCEL_API}${path}`\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new VercelApiError(response.status)\n }\n\n return response.json() as Promise<T>\n}\n\n/**\n * 递归收集目录中的所有文件\n *\n * @param dir - 目录路径\n * @param baseDir - 基础目录(用于计算相对路径)\n * @returns 文件相对路径列表\n */\nfunction collectFiles(dir: string, baseDir: string): string[] {\n const results: string[] = []\n const entries = readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...collectFiles(fullPath, baseDir))\n }\n else {\n results.push(relative(baseDir, fullPath).split(sep).join('/'))\n }\n }\n\n return results\n}\n\n// ─── Provider 工厂 ───\n\n/**\n * 创建 Vercel 部署 Provider\n * @returns DeployProvider 实例\n * @example 模块内部上下文\n * ```ts\n * const provider = createVercelProvider()\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const result = await provider.authenticate(token)\n * if (!result.success) throw new Error(result.error.message)\n * ```\n */\nexport function createVercelProvider(): DeployProvider {\n let token: string | null = null\n\n return {\n name: 'vercel',\n\n async authenticate(apiToken: string): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Vercel')\n try {\n const user = await vercelFetch<{ user: { username: string, email: string } }>(\n apiToken,\n '/v2/user',\n )\n token = apiToken\n const username = user.user.username || user.user.email\n logger.info('Vercel authenticated', { user: username })\n return ok(username)\n }\n catch (error) {\n logger.error('Vercel authentication failed', { error })\n return err(toDeployError(HaiDeployError.AUTH_FAILED, 'deploy_authFailed', error))\n }\n },\n\n async createProject(projectName: string): Promise<HaiResult<string>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Creating Vercel project', { projectName })\n try {\n // 先查找已有项目\n const existingId = await findExistingProject(token, projectName)\n if (existingId !== null) {\n logger.info('Vercel project found', { projectName, projectId: existingId })\n return ok(existingId)\n }\n\n try {\n const project = await vercelFetch<{ id: string }>(\n token,\n '/v11/projects',\n {\n method: 'POST',\n body: JSON.stringify({\n name: projectName,\n framework: 'sveltekit',\n }),\n },\n )\n logger.info('Vercel project created', { projectName, projectId: project.id })\n return ok(project.id)\n }\n catch (error) {\n // 官方文档说明同名项目创建会返回 409;遇到并发竞争时回查现有项目即可实现幂等。\n if (error instanceof VercelApiError && error.status === 409) {\n const concurrentProjectId = await findExistingProject(token, projectName)\n if (concurrentProjectId !== null) {\n logger.info('Vercel project reused after create conflict', {\n projectName,\n projectId: concurrentProjectId,\n })\n return ok(concurrentProjectId)\n }\n }\n throw error\n }\n }\n catch (error) {\n logger.error('Vercel project creation failed', { projectName, error })\n return err(toDeployError(HaiDeployError.PROJECT_CREATE_FAILED, 'deploy_projectCreateFailed', error))\n }\n },\n\n async setEnvVars(projectId: string, envVars: Record<string, string>): Promise<HaiResult<void>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Setting Vercel env vars', { projectId, count: Object.keys(envVars).length })\n try {\n const envEntries = Object.entries(envVars).map(([key, value]) => ({\n key,\n value,\n type: 'encrypted' as const,\n target: ['production', 'preview', 'development'],\n }))\n\n // Vercel 官方 `upsert=true` 支持按 key 覆盖已有环境变量,避免重复部署时报“已存在”。\n await vercelFetch(\n token,\n `/v10/projects/${projectId}/env?upsert=true`,\n {\n method: 'POST',\n body: JSON.stringify(envEntries),\n },\n )\n logger.info('Vercel env vars set', { projectId, count: envEntries.length })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Vercel env vars setup failed', { projectId, error })\n return err(toDeployError(HaiDeployError.ENV_VAR_FAILED, 'deploy_envVarFailed', error))\n }\n },\n\n async deploy(projectId: string, outputDir: string): Promise<HaiResult<DeployResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Deploying to Vercel', { projectId, outputDir })\n try {\n // 只接受 Build Output API v3;不把普通源码交给平台重新构建。\n const outputConfig = JSON.parse(readFileSync(join(outputDir, 'config.json'), 'utf8')) as { version?: unknown }\n if (outputConfig.version !== 3)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n // 收集所有文件\n const filePaths = collectFiles(outputDir, outputDir)\n const files: Array<{ file: string, sha: string, size: number }> = []\n\n // 上传每个文件\n for (const filePath of filePaths) {\n const fullPath = join(outputDir, filePath)\n const content = readFileSync(fullPath)\n const sha = createHash('sha1').update(content).digest('hex')\n const size = statSync(fullPath).size\n\n await uploadFile(token, content, sha)\n files.push({ file: `.vercel/output/${filePath}`, sha, size })\n }\n\n logger.debug('Files uploaded', { count: files.length })\n\n // 创建部署\n const deployment = await vercelFetch<{ id: string, url: string }>(\n token,\n '/v13/deployments?prebuilt=1',\n {\n method: 'POST',\n body: JSON.stringify({\n name: projectId,\n files,\n version: 2,\n project: projectId,\n projectSettings: { framework: null, buildCommand: '', installCommand: '' },\n }),\n },\n )\n\n // 轮询部署状态\n const finalStatus = await pollDeploymentStatus(token, deployment.id)\n\n const result: DeployResult = {\n url: `https://${deployment.url}`,\n deploymentId: deployment.id,\n status: finalStatus,\n envVarsSet: [],\n }\n\n logger.info('Vercel deployment complete', {\n deploymentId: deployment.id,\n url: result.url,\n status: finalStatus,\n })\n\n return ok(result)\n }\n catch (error) {\n logger.error('Vercel deployment failed', { projectId, error })\n return err(toDeployError(HaiDeployError.UPLOAD_FAILED, 'deploy_uploadFailed', error))\n }\n },\n }\n}\n\n// ─── 内部辅助 ───\n\n/**\n * 查找已有的 Vercel 项目\n *\n * @param token - API Token\n * @param projectName - 项目名称\n * @returns 项目 ID,不存在时返回 null\n */\nasync function findExistingProject(token: string, projectName: string): Promise<string | null> {\n try {\n const project = await vercelFetch<{ id: string }>(token, `/v10/projects/${projectName}`)\n return project.id\n }\n catch (error) {\n if (error instanceof VercelApiError && error.status === 404) {\n return null\n }\n throw error\n }\n}\n\n/**\n * 上传单个文件到 Vercel\n *\n * @param token - API Token\n * @param content - 文件内容\n * @param sha - 文件 SHA1 哈希\n */\nasync function uploadFile(token: string, content: Uint8Array, sha: string): Promise<void> {\n const url = `${VERCEL_API}/v2/files`\n const uploadContent = new Uint8Array(content)\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/octet-stream',\n 'x-vercel-digest': sha,\n },\n body: new Blob([uploadContent]),\n })\n\n if (!response.ok && response.status !== 409) {\n // 409 表示文件已存在,可忽略\n throw new Error(deployM('deploy_fileUploadFailed', { params: { status: String(response.status) } }))\n }\n}\n\n/**\n * 轮询部署状态直到完成\n *\n * @param token - API Token\n * @param deploymentId - 部署 ID\n * @returns 最终状态\n */\nasync function pollDeploymentStatus(\n token: string,\n deploymentId: string,\n): Promise<'ready' | 'building' | 'error'> {\n for (let i = 0; i < MAX_POLL_ATTEMPTS; i++) {\n const deployment = await vercelFetch<{ readyState: string }>(\n token,\n `/v13/deployments/${deploymentId}`,\n )\n\n if (deployment.readyState === 'READY') {\n return 'ready'\n }\n if (deployment.readyState === 'ERROR' || deployment.readyState === 'CANCELED') {\n return 'error'\n }\n\n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL))\n }\n\n // 超时仍在构建\n return 'building'\n}\n","/**\n * @h-ai/deploy — Aliyun SMS Provisioner\n *\n * 验证阿里云 API 凭证用于短信服务。 阿里云短信资源(签名/模板)通常在控制台预配置,此 Provisioner 仅验证凭证。\n * @module deploy-provisioner-aliyun\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-aliyun' })\n\n/**\n * 创建 Aliyun SMS Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const accessKeyId = process.env.HAI_DEPLOY_SERVICES_SMS_ACCESSKEYID\n * if (!accessKeyId) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_ACCESSKEYID privately')\n * const accessKeySecret = process.env.HAI_DEPLOY_SERVICES_SMS_ACCESSKEYSECRET\n * if (!accessKeySecret) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_ACCESSKEYSECRET privately')\n * const signName = process.env.HAI_DEPLOY_SERVICES_SMS_SIGNNAME\n * if (!signName) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_SIGNNAME privately')\n * const provisioner = createAliyunProvisioner()\n * const authenticated = await provisioner.authenticate({ accessKeyId, accessKeySecret, signName })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createAliyunProvisioner(): ServiceProvisioner {\n let accessKey: string | null = null\n let secretKey: string | null = null\n let signName = ''\n\n return {\n name: 'aliyun',\n serviceType: 'sms',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Aliyun')\n try {\n const akId = credentials.accessKeyId ?? credentials.access_key_id ?? credentials.access_key ?? ''\n const akSecret = credentials.accessKeySecret ?? credentials.access_key_secret ?? credentials.secret_key ?? ''\n\n if (!akId || !akSecret || !credentials.signName) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'accessKeyId, accessKeySecret, signName' } }))\n }\n\n accessKey = akId\n secretKey = akSecret\n signName = credentials.signName\n logger.info('Aliyun authenticated', { accessKeyId: `${akId.slice(0, 6)}***` })\n return ok(akId)\n }\n catch (error) {\n logger.error('Aliyun authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(_appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!accessKey || !secretKey) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Aliyun SMS service')\n\n // 阿里云短信不支持 API 创建资源,仅返回凭证作为环境变量\n return ok({\n serviceType: 'sms',\n provisionerName: 'aliyun',\n resourceStatus: 'reused',\n envVars: {\n HAI_REACH_PROVIDERS: JSON.stringify([{ name: 'sms', type: 'aliyun-sms', accessKeyId: accessKey, accessKeySecret: secretKey, signName }]),\n },\n resourceInfo: 'aliyun:verify-only',\n })\n },\n }\n}\n","/**\n * @h-ai/deploy — Neon PostgreSQL Provisioner\n *\n * 通过 Neon REST API 自动创建 PostgreSQL 数据库。\n * @module deploy-provisioner-neon\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { recoveryFailure } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-neon' })\n\n/** Neon API 基址 */\nconst NEON_API = 'https://console.neon.tech/api/v2'\n\n/** Neon 新建项目默认生成的数据库名。 */\nconst DEFAULT_NEON_DATABASE_NAME = 'neondb'\n\n/** Neon 新建项目默认生成的角色名。 */\nconst DEFAULT_NEON_ROLE_NAME = 'neondb_owner'\n\n/**\n * Neon 列表中用于按名称核对现有资源的字段。\n * @example 模块内部上下文\n * ```ts\n * const project: NeonProjectSummary = { id: 'project-shop', name: 'shop' }\n * ```\n */\ninterface NeonProjectSummary {\n id: string\n name: string\n}\n\n/**\n * 列表字段可缺失;调用方不能将请求失败解释为资源不存在。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonProjectsResponse = { projects: [{ id: 'project-shop', name: 'shop' }] }\n * const existing = response.projects?.find(project => project.name === 'shop')\n * ```\n */\ninterface NeonProjectsResponse {\n projects?: NeonProjectSummary[]\n}\n\n/**\n * 创建回执的可选形状;连接 URI 可能包含口令,不得输出。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonCreateProjectResponse = { project: { id: 'project-shop' } }\n * const id = response.project?.id // 无连接 URI 时再按已确认 ID 读取,不能重新创建。\n * ```\n */\ninterface NeonCreateProjectResponse {\n connection_uris?: Array<{ connection_uri?: string }>\n project?: { id?: string }\n}\n\n/**\n * 连接读取回执;真实 URI 可能含密码,必须作为私有配置处理。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonConnectionUriResponse = { uri: 'postgresql://app@db.example.org/shop' }\n * const present = Boolean(response.uri)\n * ```\n */\ninterface NeonConnectionUriResponse {\n uri?: string\n}\n\n/** 统一发起 Neon API 请求。 */\nasync function neonFetch<T>(token: string, path: string, options?: RequestInit): Promise<T> {\n const response = await fetch(`${NEON_API}${path}`, {\n ...options,\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Neon', status: String(response.status) } }))\n }\n\n return response.json() as Promise<T>\n}\n\n/** 列出当前账号下的 Neon 项目。 */\nasync function listNeonProjects(token: string): Promise<NeonProjectSummary[]> {\n const data = await neonFetch<NeonProjectsResponse>(token, '/projects')\n return data.projects ?? []\n}\n\n/** 按名称查找已有的 Neon 项目。 */\nasync function findExistingNeonProject(token: string, projectName: string): Promise<NeonProjectSummary | null> {\n const projects = await listNeonProjects(token)\n return projects.find(project => project.name === projectName) ?? null\n}\n\n/**\n * 获取现有项目的连接串。\n *\n * Neon 官方 OpenAPI 提供 `GET /projects/{project_id}/connection_uri`。\n * 这里使用创建项目时的默认数据库/角色名,保证本模块创建的项目可被幂等复用。\n */\nasync function getNeonConnectionUri(token: string, projectId: string): Promise<string> {\n const query = new URLSearchParams({\n database_name: DEFAULT_NEON_DATABASE_NAME,\n role_name: DEFAULT_NEON_ROLE_NAME,\n })\n const data = await neonFetch<NeonConnectionUriResponse>(\n token,\n `/projects/${projectId}/connection_uri?${query.toString()}`,\n { headers: { 'Content-Type': 'application/json' } },\n )\n\n if (!data.uri) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Neon' } }))\n }\n\n return data.uri\n}\n\n/** 构建统一的 Neon 开通结果。 */\nfunction buildNeonProvisionResult(projectId: string, connectionUri: string, resourceStatus: 'created' | 'reused'): ProvisionResult {\n return {\n serviceType: 'db',\n provisionerName: 'neon',\n resourceStatus,\n envVars: {\n HAI_DB: JSON.stringify({ type: 'postgresql', url: connectionUri, database: decodeURIComponent(new URL(connectionUri).pathname.slice(1)) }),\n },\n resourceInfo: `neon-project:${projectId}`,\n }\n}\n\n/**\n * 创建 Neon PostgreSQL Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_DB_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_DB_APIKEY privately')\n * const provisioner = createNeonProvisioner()\n * const authenticated = await provisioner.authenticate({ apiKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createNeonProvisioner(): ServiceProvisioner {\n let token: string | null = null\n\n return {\n name: 'neon',\n serviceType: 'db',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Neon')\n try {\n const apiToken = credentials.apiKey ?? credentials.token ?? credentials.api_key ?? ''\n if (!apiToken) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'token' } }))\n }\n\n await listNeonProjects(apiToken)\n token = apiToken\n logger.info('Neon authenticated')\n return ok('neon-user')\n }\n catch (error) {\n logger.error('Neon authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Neon database', { appName })\n let resource: { resourceInfo: string, resourceStatus: 'created' | 'reused' } | undefined\n try {\n const projectName = `${appName}-db`\n\n const existingProject = await findExistingNeonProject(token, projectName)\n if (existingProject !== null) {\n resource = { resourceInfo: `neon-project:${existingProject.id}`, resourceStatus: 'reused' }\n const connectionUri = await getNeonConnectionUri(token, existingProject.id)\n logger.info('Neon project reused', {\n projectId: existingProject.id,\n projectName,\n })\n return ok(buildNeonProvisionResult(existingProject.id, connectionUri, 'reused'))\n }\n\n const data = await neonFetch<NeonCreateProjectResponse>(token, '/projects', {\n method: 'POST',\n body: JSON.stringify({\n project: {\n name: projectName,\n pg_version: 16,\n },\n }),\n })\n\n const projectId = data.project?.id ?? ''\n if (projectId)\n resource = { resourceInfo: `neon-project:${projectId}`, resourceStatus: 'created' }\n const connectionUri = data.connection_uris?.[0]?.connection_uri ?? ''\n if (!projectId || !connectionUri) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Neon' } }))\n }\n\n logger.info('Neon database provisioned', { projectId })\n\n return ok(buildNeonProvisionResult(projectId, connectionUri, 'created'))\n }\n catch (error) {\n logger.error('Neon provisioning failed', { appName })\n if (resource) {\n return recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: '' }, {\n projectName: appName,\n stage: 'provision:db',\n resources: [{ serviceType: 'db', provisionerName: 'neon', ...resource }],\n })\n }\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'neon',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — Cloudflare R2 Provisioner\n *\n * 通过 Cloudflare API 自动创建 R2 存储桶。\n * @module deploy-provisioner-r2\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-r2' })\n\n/** Cloudflare API 基址 */\nconst CF_API = 'https://api.cloudflare.com/client/v4'\n\n/**\n * 创建 Cloudflare R2 Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const accountId = process.env.HAI_DEPLOY_SERVICES_STORAGE_ACCOUNTID\n * if (!accountId) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_ACCOUNTID privately')\n * const apiToken = process.env.HAI_DEPLOY_SERVICES_STORAGE_APITOKEN\n * if (!apiToken) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_APITOKEN privately')\n * const accessKeyId = process.env.HAI_DEPLOY_SERVICES_STORAGE_ACCESSKEYID\n * if (!accessKeyId) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_ACCESSKEYID privately')\n * const secretAccessKey = process.env.HAI_DEPLOY_SERVICES_STORAGE_SECRETACCESSKEY\n * if (!secretAccessKey) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_SECRETACCESSKEY privately')\n * const provisioner = createR2Provisioner()\n * const authenticated = await provisioner.authenticate({ accountId, apiToken, accessKeyId, secretAccessKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createR2Provisioner(): ServiceProvisioner {\n let token: string | null = null\n let accountId: string | null = null\n let accessKey = ''\n let secretKey = ''\n\n return {\n name: 'r2',\n serviceType: 'storage',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Cloudflare')\n try {\n const acctId = credentials.accountId ?? credentials.account_id ?? ''\n const apiTok = credentials.apiToken ?? credentials.api_token ?? credentials.token ?? ''\n if (!acctId || !apiTok || !credentials.accessKeyId || !credentials.secretAccessKey) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'accountId, apiToken, accessKeyId, secretAccessKey' } }))\n }\n\n const res = await fetch(`${CF_API}/accounts/${acctId}/r2/buckets`, {\n headers: { Authorization: `Bearer ${apiTok}` },\n })\n if (!res.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Cloudflare', status: String(res.status) } }))\n }\n\n accountId = acctId\n token = apiTok\n accessKey = credentials.accessKeyId\n secretKey = credentials.secretAccessKey\n logger.info('Cloudflare R2 authenticated', { accountId: acctId })\n return ok(acctId)\n }\n catch (error) {\n logger.error('Cloudflare R2 authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token || !accountId) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n const bucketName = `${appName}-storage`.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n\n logger.debug('Provisioning R2 bucket', { appName, bucketName })\n try {\n // 创建桶\n const createRes = await fetch(\n `${CF_API}/accounts/${accountId}/r2/buckets`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ name: bucketName }),\n },\n )\n\n // 409 表示桶已存在,可继续\n if (!createRes.ok && createRes.status !== 409) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Cloudflare', status: String(createRes.status) } }))\n }\n\n logger.info('R2 bucket provisioned', { bucketName })\n\n return ok({\n serviceType: 'storage',\n provisionerName: 'r2',\n resourceStatus: createRes.status === 409 ? 'reused' : 'created',\n envVars: {\n HAI_STORAGE: JSON.stringify({\n type: 's3',\n endpoint: `https://${accountId}.r2.cloudflarestorage.com`,\n bucket: bucketName,\n region: 'auto',\n accessKeyId: accessKey,\n secretAccessKey: secretKey,\n }),\n },\n resourceInfo: `r2-bucket:${bucketName}`,\n })\n }\n catch (error) {\n logger.error('R2 provisioning failed', { appName, error })\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'r2',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — Resend Email Provisioner\n *\n * 通过 Resend REST API 验证 API Key 并获取域信息。 Resend 不支持通过 API 创建账户,此 Provisioner 仅验证已有凭证。\n * @module deploy-provisioner-resend\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-resend' })\n\n/** Resend API 基址 */\nconst RESEND_API = 'https://api.resend.com'\n\n/**\n * 创建 Resend Email Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_EMAIL_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_EMAIL_APIKEY privately')\n * const from = process.env.HAI_DEPLOY_SERVICES_EMAIL_FROM\n * if (!from) throw new Error('Provide HAI_DEPLOY_SERVICES_EMAIL_FROM privately')\n * const provisioner = createResendProvisioner()\n * const authenticated = await provisioner.authenticate({ apiKey, from })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createResendProvisioner(): ServiceProvisioner {\n let token: string | null = null\n let from = ''\n\n return {\n name: 'resend',\n serviceType: 'email',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Resend')\n try {\n const apiToken = credentials.apiKey ?? credentials.api_key ?? credentials.token ?? ''\n if (!apiToken || !credentials.from) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'apiKey, from' } }))\n }\n\n const res = await fetch(`${RESEND_API}/domains`, {\n headers: { Authorization: `Bearer ${apiToken}` },\n })\n if (!res.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Resend', status: String(res.status) } }))\n }\n token = apiToken\n from = credentials.from\n logger.info('Resend authenticated')\n return ok('resend-user')\n }\n catch (error) {\n logger.error('Resend authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(_appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Resend email service')\n\n // Resend 不支持 API 创建资源,仅返回凭证作为环境变量\n return ok({\n serviceType: 'email',\n provisionerName: 'resend',\n resourceStatus: 'reused',\n envVars: {\n HAI_REACH_PROVIDERS: JSON.stringify([{ name: 'email', type: 'smtp', host: 'smtp.resend.com', port: 465, secure: true, user: 'resend', pass: token, from }]),\n },\n resourceInfo: 'resend:verify-only',\n })\n },\n }\n}\n","/**\n * @h-ai/deploy — Upstash Redis Provisioner\n *\n * 通过 Upstash REST API 自动创建 Redis 数据库。\n * @module deploy-provisioner-upstash\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { Buffer } from 'node:buffer'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { deployM } from '../deploy-i18n.js'\nimport { recoveryFailure } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-upstash' })\n\n/** Upstash API 基址 */\nconst UPSTASH_API = 'https://api.upstash.com'\n\n/**\n * 供应商 API 的部分字段形状;缺少连接凭据时不能声称已有连接可用。\n * @example 模块内部上下文\n * ```ts\n * const database: UpstashDatabase = { database_id: 'redis-shop', database_name: 'shop', endpoint: 'redis.example.org', port: 6379 }\n * const id = database.database_id\n * ```\n */\ninterface UpstashDatabase {\n database_id?: string\n database_name?: string\n endpoint?: string\n port?: number\n password?: string\n}\n\n/** 构建 Upstash Developer API 的 Basic Auth 请求头。 */\nfunction createUpstashAuthHeader(email: string, apiKey: string): string {\n return `Basic ${Buffer.from(`${email}:${apiKey}`).toString('base64')}`\n}\n\n/** 统一发起 Upstash Developer API 请求。 */\nasync function upstashFetch<T>(\n email: string,\n apiKey: string,\n path: string,\n options?: RequestInit,\n): Promise<T> {\n const response = await fetch(`${UPSTASH_API}${path}`, {\n ...options,\n headers: {\n 'Authorization': createUpstashAuthHeader(email, apiKey),\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Upstash', status: String(response.status) } }))\n }\n\n return response.json() as Promise<T>\n}\n\n/** 列出当前账号下的所有 Upstash 数据库。 */\nasync function listUpstashDatabases(email: string, apiKey: string): Promise<UpstashDatabase[]> {\n return upstashFetch<UpstashDatabase[]>(email, apiKey, '/v2/redis/databases')\n}\n\n/** 按数据库名查找已有资源。 */\nasync function findExistingUpstashDatabase(\n email: string,\n apiKey: string,\n databaseName: string,\n): Promise<UpstashDatabase | null> {\n const databases = await listUpstashDatabases(email, apiKey)\n return databases.find(database => database.database_name === databaseName) ?? null\n}\n\n/** 获取单个数据库详情。 */\nasync function getUpstashDatabase(email: string, apiKey: string, databaseId: string): Promise<UpstashDatabase> {\n return upstashFetch<UpstashDatabase>(email, apiKey, `/v2/redis/database/${databaseId}`)\n}\n\n/** 将 Upstash 响应转换为 deploy 统一结果。 */\nfunction buildUpstashProvisionResult(database: UpstashDatabase, resourceStatus: 'created' | 'reused'): ProvisionResult {\n const databaseId = database.database_id ?? ''\n\n if (!databaseId || !database.endpoint || !database.password || !database.port) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Upstash' } }))\n }\n\n return {\n serviceType: 'cache',\n provisionerName: 'upstash',\n resourceStatus,\n envVars: {\n HAI_CACHE: JSON.stringify({ type: 'redis', url: `rediss://default:${encodeURIComponent(database.password)}@${database.endpoint}:${database.port}` }),\n },\n resourceInfo: `upstash-db:${databaseId}`,\n }\n}\n\n/**\n * 创建 Upstash Redis Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const email = process.env.HAI_DEPLOY_SERVICES_CACHE_EMAIL\n * if (!email) throw new Error('Provide HAI_DEPLOY_SERVICES_CACHE_EMAIL privately')\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_CACHE_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_CACHE_APIKEY privately')\n * const provisioner = createUpstashProvisioner()\n * const authenticated = await provisioner.authenticate({ email, apiKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createUpstashProvisioner(): ServiceProvisioner {\n let apiKey: string | null = null\n let email: string | null = null\n\n return {\n name: 'upstash',\n serviceType: 'cache',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Upstash')\n try {\n const userEmail = credentials.email ?? ''\n const userKey = credentials.apiKey ?? credentials.api_key ?? credentials.token ?? ''\n if (!userEmail || !userKey) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'email, api_key' } }))\n }\n\n await listUpstashDatabases(userEmail, userKey)\n\n email = userEmail\n apiKey = userKey\n logger.info('Upstash authenticated', { email: userEmail })\n return ok(userEmail)\n }\n catch (error) {\n logger.error('Upstash authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!apiKey || !email) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Upstash Redis', { appName })\n let resource: { resourceInfo: string, resourceStatus: 'created' | 'reused' } | undefined\n try {\n const databaseName = `${appName}-cache`\n\n const existingDatabase = await findExistingUpstashDatabase(email, apiKey, databaseName)\n if (existingDatabase !== null) {\n const databaseId = existingDatabase.database_id ?? ''\n if (!databaseId) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Upstash' } }))\n }\n\n resource = { resourceInfo: `upstash-db:${databaseId}`, resourceStatus: 'reused' }\n const detail = await getUpstashDatabase(email, apiKey, databaseId)\n logger.info('Upstash Redis reused', { databaseId, databaseName })\n return ok(buildUpstashProvisionResult({ ...existingDatabase, ...detail }, 'reused'))\n }\n\n const data = await upstashFetch<UpstashDatabase>(email, apiKey, '/v2/redis/database', {\n method: 'POST',\n body: JSON.stringify({\n name: databaseName,\n region: 'global',\n tls: true,\n }),\n })\n\n if (data.database_id)\n resource = { resourceInfo: `upstash-db:${data.database_id}`, resourceStatus: 'created' }\n logger.info('Upstash Redis provisioned', { databaseId: data.database_id })\n\n return ok(buildUpstashProvisionResult(data, 'created'))\n }\n catch (error) {\n logger.error('Upstash provisioning failed', { appName })\n if (resource) {\n return recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: '' }, {\n projectName: appName,\n stage: 'provision:cache',\n resources: [{ serviceType: 'cache', provisionerName: 'upstash', ...resource }],\n })\n }\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'upstash',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — 模块主入口\n *\n * 提供 deploy 单例对象,暴露完整的自动化部署 API。\n * @module deploy-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ContainerDeployProvider } from './container/deploy-container-types.js'\nimport type { DeployConfig, DeployConfigInput } from './deploy-config.js'\nimport type { DeployProvider, ServiceProvisioner } from './deploy-internal-types.js'\nimport type {\n DeployAppOptions,\n DeployCredentialOperations,\n DeployFunctions,\n DeployRecoveryInfo,\n DeployResult,\n DeployScanOptions,\n ProvisionResult,\n ScanResult,\n ServiceType,\n} from './deploy-types.js'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { readDeploymentArtifact } from './deploy-artifact.js'\nimport { DeployConfigSchema } from './deploy-config.js'\nimport {\n getCredentialsPath,\n loadCredentials,\n saveCredential,\n saveCredentials,\n} from './deploy-credentials.js'\nimport { loadDeploymentEnvironment, saveDeploymentEnvironment } from './deploy-environment.js'\nimport { normalizeProjectName, resolveArtifactDirectory, resolveOutputDir, resolveProjectDirectory, usesDefaultMiddleware } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { mergeManagedMiddlewareConfig } from './deploy-middleware-config.js'\nimport { getDeployRecovery, recoveryFailure } from './deploy-recovery.js'\nimport { scanApp } from './deploy-scanner.js'\nimport { HaiDeployError } from './deploy-types.js'\nimport { createDockerSshProvider } from './providers/deploy-provider-docker-ssh.js'\nimport { createVercelProvider } from './providers/deploy-provider-vercel.js'\nimport { createAliyunProvisioner } from './provisioners/deploy-provisioner-aliyun.js'\nimport { createNeonProvisioner } from './provisioners/deploy-provisioner-neon.js'\nimport { createR2Provisioner } from './provisioners/deploy-provisioner-r2.js'\nimport { createResendProvisioner } from './provisioners/deploy-provisioner-resend.js'\nimport { createUpstashProvisioner } from './provisioners/deploy-provisioner-upstash.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'main' })\n\n// ─── 内部状态 ───\n\nlet currentConfig: DeployConfig | null = null\nlet currentProvider: DeployProvider | null = null\nlet currentContainerProvider: ContainerDeployProvider | null = null\nconst currentProvisioners: Map<ServiceType, ServiceProvisioner> = new Map()\n\n/** 并发初始化防护标志 */\nlet initInProgress = false\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiDeployError.NOT_INITIALIZED,\n () => deployM('deploy_notInitialized'),\n)\n\n// ─── Provider 工厂 ───\n\n/**\n * 根据配置类型创建对应的 DeployProvider\n *\n * @param type - Provider 类型\n * @returns DeployProvider 实例\n */\nfunction createProviderByType(type: string): DeployProvider {\n switch (type) {\n case 'vercel':\n return createVercelProvider()\n default:\n throw new Error(deployM('deploy_unsupportedProviderType', { params: { type } }))\n }\n}\n\n// ─── Provisioner 工厂 ───\n\n/**\n * 根据 provisioner 名称创建对应的 ServiceProvisioner\n *\n * @param provisioner - Provisioner 标识\n * @returns ServiceProvisioner 实例\n */\nfunction createProvisionerByName(provisioner: string): ServiceProvisioner {\n switch (provisioner) {\n case 'neon':\n return createNeonProvisioner()\n case 'upstash':\n return createUpstashProvisioner()\n case 'cloudflare-r2':\n return createR2Provisioner()\n case 'resend':\n return createResendProvisioner()\n case 'aliyun':\n return createAliyunProvisioner()\n default:\n throw new Error(deployM('deploy_unsupportedProvisionerType', { params: { type: provisioner } }))\n }\n}\n\n/**\n * 从配置中提取 provisioner 凭证并转为 Record<string, string>\n *\n * @param serviceConfig - 服务配置对象\n * @returns 凭证键值对\n */\nfunction extractCredentials(serviceConfig: Record<string, unknown>): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(serviceConfig)) {\n if (key !== 'provisioner' && typeof value === 'string') {\n result[key] = value\n }\n }\n return result\n}\n\n/**\n * Deploy 凭证子功能。\n *\n * 这些操作仅处理本地 `~/.hai/credentials.yml`,供 CLI 在读取项目 `hai.json` 的部署配置\n * 之前注入 `HAI_DEPLOY_*` 环境变量,因此不依赖 `deploy.init()`。\n */\nconst deployCredentials: DeployCredentialOperations = {\n getPath: () => getCredentialsPath(),\n load: () => loadCredentials(),\n save: (key: string, value: string) => saveCredential(key, value),\n saveAll: (entries: Record<string, string>) => saveCredentials(entries),\n}\n\n/** 合并 Provisioner 输出环境变量,并聚合 HAI_REACH_PROVIDERS 数组。 */\nfunction mergeProvisionEnv(results: ProvisionResult[], scan?: ScanResult, options?: DeployAppOptions): Record<string, string> {\n const env: Record<string, string> = {}\n const reachRequirements = scan?.middlewares?.filter(item => item.configName === 'reach') ?? []\n const reachProviders: unknown[] = reachRequirements.map(item => item.config)\n let hasReachOutput = false\n for (const prov of results) {\n if (prov.envVars.HAI_REACH_PROVIDERS) {\n hasReachOutput = true\n const supplied = JSON.parse(prov.envVars.HAI_REACH_PROVIDERS) as Record<string, unknown>[]\n for (const provider of supplied) {\n const targets = reachRequirements.filter((item) => {\n const mode = options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.[item.service]\n return item.service === prov.serviceType && (!mode || mode === 'default')\n })\n if (targets.length) {\n for (const target of targets)\n reachProviders[reachRequirements.indexOf(target)] = { ...mergeManagedMiddlewareConfig(target, provider), name: target.config.name ?? provider.name }\n }\n else {\n reachProviders.push(provider)\n }\n }\n }\n for (const [name, value] of Object.entries(prov.envVars)) {\n const requirement = scan?.middlewares?.find(item => item.envPrefix === name)\n env[name] = requirement ? JSON.stringify(mergeManagedMiddlewareConfig(requirement, JSON.parse(value))) : value\n }\n }\n if (hasReachOutput)\n env.HAI_REACH_PROVIDERS = JSON.stringify(reachProviders)\n return env\n}\n\n// ─── 模块单例 ───\n\n/**\n * Deploy 模块单例\n * 每次 init 检查 HaiResult;只打包不会连接 SSH,成功打包也不代表服务器已部署。远端 unknown 必须先核对匹配部署 ID 的结果,不能盲目重试。\n * @example\n * ```ts\n * import { deploy, getDeployCommandState } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 当前项目已有镜像产物与部署环境;只打包,不连接服务器。\n * const result = await deploy.deployApp(process.cwd(), { environment: 'prod', bundleOnly: true })\n * if (!result.success) {\n * const state = getDeployCommandState(result.error)\n * if (state?.remoteExecution === 'unknown') {\n * process.stderr.write('Inspect the matching server result before retrying\\n')\n * }\n * throw new Error(result.error.message)\n * }\n * if (result.data.status === 'packaged') {\n * const bundle = result.data.bundlePath\n * }\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\nexport const deploy: DeployFunctions = {\n credentials: deployCredentials,\n\n async init(config: DeployConfigInput): Promise<HaiResult<void>> {\n // 并发初始化防护:避免多次 init 同时执行导致资源泄漏\n if (initInProgress) {\n logger.warn('Deploy init already in progress, skipping concurrent call')\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', { params: { error: 'init already in progress' } }),\n )\n }\n initInProgress = true\n\n try {\n if (currentProvider || currentContainerProvider) {\n logger.warn('Deploy module is already initialized, reinitializing')\n await deploy.close()\n }\n\n logger.info('Initializing deploy module')\n\n const parseResult = DeployConfigSchema.safeParse(config)\n if (!parseResult.success) {\n logger.error('Deploy config validation failed', { error: parseResult.error.message })\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', { params: { error: parseResult.error.message } }),\n parseResult.error,\n )\n }\n const parsed = parseResult.data\n\n try {\n // 创建部署 Provider:docker-ssh 走容器路径(无远程认证),其余走平台路径并即时认证\n let provider: DeployProvider | null = null\n let containerProvider: ContainerDeployProvider | null = null\n if (parsed.provider.type === 'docker-ssh') {\n containerProvider = createDockerSshProvider(parsed.provider, parsed.container)\n logger.info('Container deploy provider ready', { provider: 'docker-ssh', host: parsed.provider.ssh?.host })\n }\n else {\n provider = createProviderByType(parsed.provider.type)\n const authResult = await provider.authenticate(parsed.provider.token)\n if (!authResult.success) {\n return err(authResult.error)\n }\n logger.info('Provider authenticated', { provider: parsed.provider.type, user: authResult.data })\n }\n\n // 创建 Provisioners(两类 Provider 均可复用云资源开通)\n currentProvisioners.clear()\n if (parsed.services) {\n const serviceEntries = Object.entries(parsed.services) as Array<[ServiceType, Record<string, unknown> | undefined]>\n for (const [serviceType, serviceConfig] of serviceEntries) {\n if (!serviceConfig)\n continue\n\n const provisioner = createProvisionerByName(serviceConfig.provisioner as string)\n const credentials = extractCredentials(serviceConfig as Record<string, unknown>)\n const provAuthResult = await provisioner.authenticate(credentials)\n if (!provAuthResult.success) {\n logger.error('Provisioner authentication failed', {\n service: serviceType,\n provisioner: (serviceConfig as Record<string, unknown>).provisioner,\n })\n currentProvisioners.clear()\n return err(provAuthResult.error)\n }\n logger.info('Provisioner authenticated', {\n service: serviceType,\n user: provAuthResult.data,\n })\n currentProvisioners.set(serviceType, provisioner)\n }\n }\n\n currentProvider = provider\n currentContainerProvider = containerProvider\n currentConfig = parsed\n logger.info('Deploy module initialized', {\n provider: parsed.provider.type,\n provisioners: [...currentProvisioners.keys()],\n })\n return ok(undefined)\n }\n catch (error) {\n // 清理部分赋值的状态\n currentProvider = null\n currentContainerProvider = null\n currentConfig = null\n currentProvisioners.clear()\n logger.error('Deploy module initialization failed', { error })\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n }\n finally {\n initInProgress = false\n }\n },\n\n async close(): Promise<void> {\n if (!currentProvider && !currentContainerProvider) {\n logger.info('Deploy module already closed, skipping')\n return\n }\n\n logger.info('Closing deploy module')\n currentProvider = null\n currentContainerProvider = null\n currentConfig = null\n currentProvisioners.clear()\n logger.info('Deploy module closed')\n },\n\n get config(): DeployConfig | null {\n return currentConfig\n },\n\n get isInitialized(): boolean {\n return currentProvider !== null || currentContainerProvider !== null\n },\n\n async scan(appDir: string, options?: DeployScanOptions): Promise<HaiResult<ScanResult>> {\n // scan 仅做本地文件分析,不依赖 Provider / Provisioner 初始化状态。\n logger.debug('Scanning application', { appDir })\n return scanApp(appDir, options)\n },\n\n async provisionAll(projectName: string, services?: ServiceType[]): Promise<HaiResult<ProvisionResult[]>> {\n if (!currentProvider && !currentContainerProvider) {\n return notInitialized.result()\n }\n\n logger.info('Provisioning all services', { projectName, count: currentProvisioners.size })\n const results: ProvisionResult[] = []\n\n for (const [serviceType, provisioner] of currentProvisioners) {\n if (services && !services.includes(serviceType))\n continue\n logger.debug('Provisioning service', { serviceType, provisioner: provisioner.name })\n const provResult = await provisioner.provision(projectName)\n if (!provResult.success) {\n logger.error('Service provisioning failed', {\n serviceType,\n provisioner: provisioner.name,\n code: provResult.error.code,\n })\n return recoveryFailure(provResult.error, {\n projectName,\n stage: `provision:${serviceType}`,\n resources: [\n ...results.map(({ envVars: _envVars, ...resource }) => resource),\n ...(getDeployRecovery(provResult.error)?.resources ?? [\n { serviceType, provisionerName: provisioner.name, resourceInfo: projectName, resourceStatus: 'unknown' as const },\n ]),\n ],\n })\n }\n results.push(provResult.data)\n logger.info('Service provisioned', { serviceType, provisioner: provisioner.name })\n }\n\n return ok(results)\n },\n\n async deployApp(\n appDir: string,\n options?: DeployAppOptions,\n ): Promise<HaiResult<DeployResult>> {\n if (!currentProvider && !currentContainerProvider) {\n return notInitialized.result()\n }\n\n if (options && 'projectName' in options && options.projectName !== undefined)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameOverrideRemoved'))\n\n logger.info('Starting deployment', { appDir, environment: options?.environment })\n\n // 1. 扫描应用\n const scanOptions = { ...options, environment: options?.environment ?? currentConfig?.environment }\n const scanResult = await scanApp(appDir, scanOptions)\n if (!scanResult.success) {\n return err(scanResult.error)\n }\n const scan = scanResult.data\n appDir = scan.appDir ?? appDir\n const environment = loadDeploymentEnvironment({ environment: scanOptions.environment ?? 'prod', envDir: scan.envDir ?? appDir, requireFile: scanOptions.environment !== undefined })\n if (!environment.success)\n return environment\n // SSH 密码允许引用自定义变量名;按配置来源排除,不能按密码值删除同值的应用配置。\n const connectionVariables = new Set<string>()\n const projectFile = join(resolveProjectDirectory(appDir), 'hai.json')\n if (existsSync(projectFile)) {\n try {\n const project: { deploy?: { provider?: { ssh?: { password?: unknown } } } } = JSON.parse(readFileSync(projectFile, 'utf8'))\n const reference = project?.deploy?.provider?.ssh?.password\n if (typeof reference === 'string') {\n for (const match of reference.matchAll(/\\$\\{([^:}]+)(?::[^}]*)?\\}/g))\n connectionVariables.add(match[1]!)\n }\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path: projectFile, line: '1' } }))\n }\n }\n const appEnv = Object.fromEntries(Object.entries(environment.data.values).filter(([key]) => key !== 'HAI_DEPLOY' && !connectionVariables.has(key) && !key.startsWith('HAI_CLI_') && (!key.startsWith('HAI_DEPLOY_') || key === 'HAI_DEPLOY_ENVIRONMENT')))\n const projectName = `${normalizeProjectName(scan.appName)}${scanOptions.environment ? `-${environment.data.environment}` : ''}`\n options = {\n ...options,\n ...(scanOptions.environment ? { environment: environment.data.environment } : {}),\n ...(options?.skipMiddleware ? { serviceModes: Object.fromEntries(scan.requiredServices.map(service => [service, 'keep' as const])) } : {}),\n }\n if (options.selectedServices) {\n options.serviceModes = {\n ...options.serviceModes,\n ...Object.fromEntries(scan.requiredServices.filter(service => !options.selectedServices!.includes(service)).map(service => [service, 'keep' as const])),\n }\n }\n\n // 容器 Provider(docker-ssh):走独立的容器部署编排\n if (currentContainerProvider) {\n return deployContainerApp(currentContainerProvider, appDir, scan, projectName, options, appEnv)\n }\n\n if (options?.bundleOnly)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleOnlyContainer'))\n if (options.selectedServices)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectedContainerOnly'))\n\n // 到此必为平台 Provider(vercel)\n if (!currentProvider) {\n return notInitialized.result()\n }\n\n // 2. 检查 adapter\n if (scan.isSvelteKit && !scan.adapterInstalled) {\n return err(\n HaiDeployError.ADAPTER_MISSING,\n deployM('deploy_adapterMissing', {\n params: { adapter: '@sveltejs/adapter-vercel' },\n }),\n )\n }\n\n if (!existsSync(resolveOutputDir(appDir, 'vercel')))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n\n // 3. 开通基础设施\n let allEnvVars: Record<string, string> = appEnv\n const recovery: DeployRecoveryInfo = { projectName, stage: 'provision', resources: [] }\n if (!options?.skipMiddleware) {\n const provResults = await deploy.provisionAll(projectName, options?.serviceModes ? scan.requiredServices.filter(service => usesDefaultMiddleware(scan, service, options)) : undefined)\n if (!provResults.success) {\n return err(provResults.error)\n }\n recovery.resources = provResults.data.map(({ envVars: _envVars, ...resource }) => resource)\n allEnvVars = { ...allEnvVars, ...mergeProvisionEnv(provResults.data, scan, options) }\n if (options?.environment) {\n const saved = saveDeploymentEnvironment(environment.data, mergeProvisionEnv(provResults.data, scan, options))\n if (!saved.success)\n return recoveryFailure(saved.error, { ...recovery, stage: 'save-env' })\n }\n }\n\n // 4. 创建平台项目\n const projectResult = await currentProvider.createProject(projectName)\n if (!projectResult.success) {\n return recoveryFailure(projectResult.error, { ...recovery, stage: 'create-project' })\n }\n const projectId = projectResult.data\n recovery.platformProjectId = projectId\n\n // 5. 设置环境变量\n if (Object.keys(allEnvVars).length > 0) {\n const envResult = await currentProvider.setEnvVars(projectId, allEnvVars)\n if (!envResult.success) {\n return recoveryFailure(envResult.error, { ...recovery, stage: 'set-env' })\n }\n }\n\n // 7. 部署\n const outputDir = resolveOutputDir(appDir, currentConfig?.provider.type ?? 'vercel')\n const deployResult = await currentProvider.deploy(projectId, outputDir)\n if (!deployResult.success) {\n return recoveryFailure(deployResult.error, { ...recovery, stage: 'deploy' })\n }\n\n // 补充环境变量列表到结果中\n const result: DeployResult = {\n ...deployResult.data,\n envVarsSet: Object.keys(allEnvVars),\n }\n\n logger.info('Deployment completed', {\n url: result.url,\n deploymentId: result.deploymentId,\n status: result.status,\n })\n\n return ok(result)\n },\n}\n\n/**\n * 容器 Provider(docker-ssh)部署编排。\n *\n * 校验 adapter-node → 开通云资源(可选)→ 交由容器 Provider 完成\n * 打包 / 传输 / compose up / 健康检查。\n *\n * @param provider - 容器部署 Provider\n * @param appDir - 应用根目录\n * @param scan - 扫描结果\n * @param rawProjectName - 原始项目名(未归一化)\n * @param options - 部署选项\n */\nasync function deployContainerApp(\n provider: ContainerDeployProvider,\n appDir: string,\n scan: ScanResult,\n rawProjectName: string,\n options?: DeployAppOptions,\n appEnv: Record<string, string> = {},\n): Promise<HaiResult<DeployResult>> {\n const projectName = normalizeProjectName(rawProjectName)\n\n let artifact\n let artifactDir = options?.artifactDir ?? resolveArtifactDirectory(appDir)\n try {\n if (existsSync(join(artifactDir, 'latest'))) {\n const latest = readFileSync(join(artifactDir, 'latest'), 'utf8').trim()\n if (!/^[a-z0-9][\\w.+-]*$/i.test(latest))\n throw new Error('Invalid artifact pointer')\n artifactDir = join(artifactDir, latest)\n }\n artifact = await readDeploymentArtifact(artifactDir)\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n }\n if (artifact.partial && !options?.selectedServices) {\n const selectedServices = artifact.images.map(image => image.name)\n options = {\n ...options,\n selectedServices,\n serviceModes: {\n ...options?.serviceModes,\n ...Object.fromEntries(scan.requiredServices.map(service => [service, 'keep' as const])),\n },\n }\n }\n if (!options?.bundleOnly && currentConfig?.provider.type === 'docker-ssh' && !currentConfig.provider.ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n\n let provisionEnv: Record<string, string> = {}\n if (!options?.skipMiddleware) {\n const provResults = await deploy.provisionAll(projectName, options?.serviceModes ? scan.requiredServices.filter(service => usesDefaultMiddleware(scan, service, options)) : undefined)\n if (!provResults.success) {\n return err(provResults.error)\n }\n provisionEnv = mergeProvisionEnv(provResults.data, scan, options)\n }\n\n return provider.deploy({ appDir, artifact, artifactDir, projectName, scan, provisionEnv, appEnv, options })\n}\n","/**\n * 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。\n * 字段名与对应模块公开 Schema 保持一致,不把模块依赖等同于必须创建外部服务。\n * @module deploy-middleware\n */\nimport type { ServiceType } from './deploy-types.js'\nimport { deployM } from './deploy-i18n.js'\n\n/**\n * 连接字段;例如 `{ name: 'port', defaultValue: '5432', kind: 'port' }`。\n * @example\n * ```ts\n * import type { MiddlewareField } from '@h-ai/deploy'\n * const field: MiddlewareField = { name: 'port', defaultValue: '5432', required: true, kind: 'port' }\n * ```\n */\nexport interface MiddlewareField {\n /** 模块配置字段名,camelCase 不拆词。 */\n name: string\n /** 无现有配置时使用的提示默认值。 */\n defaultValue?: string\n /** 是否为连接所必需;可选项允许留空。 */\n required?: boolean\n /** 密码输入与私有环境文件写入标记。 */\n secret?: boolean\n /** 交互校验类型;端口范围为 1–65535。 */\n kind?: 'port' | 'boolean' | 'number' | 'url'\n /** 数值下限;未声明时为 0。 */\n minimum?: number\n /** 数值上限;例如 Redis db 为 15。 */\n maximum?: number\n}\n\n/**\n * 后端目录项;例如 PostgreSQL 对应 `backend: 'postgresql'`。\n * @example\n * ```ts\n * import type { MiddlewareBackend } from '@h-ai/deploy'\n * const backend: MiddlewareBackend = { backend: 'postgresql', label: 'PostgreSQL', purpose: 'deploy_purposeDatabase', fields: [{ name: 'database', required: true }] }\n * ```\n */\nexport interface MiddlewareBackend {\n /** 模块 Schema 接受的后端标识。 */\n backend: string\n /** 可直接识别的产品名称。 */\n label: string\n /** 用途说明的 i18n 消息键。 */\n purpose: Parameters<typeof deployM>[0]\n /** 云自动开通器;缺失表示不能自动开通该云服务。 */\n provisioner?: 'neon' | 'upstash' | 'cloudflare-r2' | 'resend' | 'aliyun'\n /** 自定义连接需要逐项输入的字段。 */\n fields: MiddlewareField[]\n}\n\nconst field = (name: string, defaultValue?: string, kind?: MiddlewareField['kind'], secret = false): MiddlewareField => ({ name, defaultValue, kind, secret })\nconst required = (name: string, defaultValue?: string, kind?: MiddlewareField['kind']): MiddlewareField => ({ ...field(name, defaultValue, kind), required: true })\n\n/**\n * 所有可部署中间件的连接目录。\n * SQLite、memory、local 与 disabled 保留本地/禁用语义,不创建无关 sidecar。\n * 目录同时描述本机、禁用、自建与云后端;存在依赖不等于必须开通新资源。\n * @example\n * ```ts\n * import { DEPLOY_MIDDLEWARE, describeMiddlewareBackend } from '@h-ai/deploy'\n * const choices = DEPLOY_MIDDLEWARE.db.map(backend => ({ value: backend.backend, description: describeMiddlewareBackend(backend) }))\n * ```\n */\nexport const DEPLOY_MIDDLEWARE: Record<ServiceType, MiddlewareBackend[]> = {\n db: [\n { backend: 'sqlite', label: 'SQLite', purpose: 'deploy_purposeSqlite', fields: [required('database', './data/app.db')] },\n ...(['postgresql', 'mysql'] as const).map(backend => ({\n backend,\n label: backend === 'mysql' ? 'MySQL' : 'PostgreSQL',\n purpose: 'deploy_purposeDatabase' as const,\n provisioner: backend === 'postgresql' ? 'neon' as const : undefined,\n fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', backend === 'mysql' ? '3306' : '5432', 'port'), required('database', 'hai'), field('user', 'hai'), field('password', '', undefined, true), field('ssl', 'false')],\n })),\n ],\n cache: [\n { backend: 'memory', label: 'Memory', purpose: 'deploy_purposeMemory', fields: [] },\n { backend: 'redis', label: 'Redis', purpose: 'deploy_purposeCache', provisioner: 'upstash', fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', '6379', 'port'), field('password', '', undefined, true), { ...field('db', '0', 'number'), maximum: 15 }, field('tls', 'false', 'boolean'), field('keyPrefix'), field('connectTimeout', '10000', 'number'), field('commandTimeout', '5000', 'number')] },\n ],\n storage: [\n { backend: 'local', label: 'Local filesystem', purpose: 'deploy_purposeLocal', fields: [required('root', './data/storage')] },\n { backend: 's3', label: 'S3 / RustFS / MinIO / Cloudflare R2', purpose: 'deploy_purposeStorage', provisioner: 'cloudflare-r2', fields: [field('endpoint', '', 'url'), required('bucket', 'hai'), required('region', 'us-east-1'), required('accessKeyId'), { ...required('secretAccessKey'), secret: true }, field('forcePathStyle', 'true', 'boolean')] },\n ],\n vecdb: [\n { backend: 'lancedb', label: 'LanceDB', purpose: 'deploy_purposeLocal', fields: [required('path', './data/vectors')] },\n { backend: 'qdrant', label: 'Qdrant', purpose: 'deploy_purposeVector', fields: [required('url', 'http://localhost:6333', 'url'), field('apiKey', '', undefined, true)] },\n { backend: 'pgvector', label: 'PostgreSQL / pgvector', purpose: 'deploy_purposeVector', fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', '5432', 'port'), required('database', 'hai'), field('user', 'hai'), field('password', '', undefined, true)] },\n { backend: 'chroma', label: 'Chroma', purpose: 'deploy_purposeVector', fields: [required('url', 'http://localhost:8000', 'url')] },\n ],\n ldap: [\n { backend: 'disabled', label: 'Disabled', purpose: 'deploy_purposeDisabled', fields: [] },\n { backend: 'ldap', label: 'LDAP / OpenLDAP', purpose: 'deploy_purposeLdap', fields: [required('url', 'ldap://localhost:389', 'url'), required('bindDn', 'cn=admin,dc=example,dc=org'), { ...required('bindPassword'), secret: true }, required('searchBase', 'dc=example,dc=org'), field('searchFilter', '(uid={{username}})'), field('usernameAttribute', 'uid'), field('emailAttribute', 'mail'), field('displayNameAttribute', 'cn'), field('useTls', 'false', 'boolean'), { ...field('connectTimeout', '5000', 'number'), minimum: 1000 }] },\n ],\n email: [\n { backend: 'console', label: 'Console', purpose: 'deploy_purposeConsole', fields: [] },\n { backend: 'smtp', label: 'SMTP', purpose: 'deploy_purposeEmail', provisioner: 'resend', fields: [required('host', 'localhost'), required('port', '465', 'port'), field('secure', 'true', 'boolean'), field('user'), field('pass', '', undefined, true), required('from', 'noreply@example.com')] },\n { backend: 'api', label: 'HTTP notification API', purpose: 'deploy_purposeEmail', fields: [required('url', '', 'url'), field('method', 'POST'), field('headers'), field('timeout', '10000', 'number')] },\n ],\n sms: [\n { backend: 'console', label: 'Console', purpose: 'deploy_purposeConsole', fields: [] },\n { backend: 'aliyun-sms', label: 'Aliyun SMS', purpose: 'deploy_purposeSms', provisioner: 'aliyun', fields: [required('accessKeyId'), { ...required('accessKeySecret'), secret: true }, required('signName'), field('endpoint', 'dysmsapi.aliyuncs.com')] },\n { backend: 'api', label: 'HTTP notification API', purpose: 'deploy_purposeSms', fields: [required('url', '', 'url'), field('method', 'POST'), field('headers'), field('timeout', '10000', 'number')] },\n ],\n}\n\n/**\n * 返回当前语言的后端用途说明。\n * @param backend - 部署目录中的后端条目。\n * @returns 当前 locale 的用途说明。\n * @example\n * ```ts\n * import { DEPLOY_MIDDLEWARE, describeMiddlewareBackend } from '@h-ai/deploy'\n * const backend = DEPLOY_MIDDLEWARE.db.find(item => item.backend === 'postgresql')\n * if (backend) {\n * const description = describeMiddlewareBackend(backend)\n * }\n * ```\n */\nexport function describeMiddlewareBackend(backend: MiddlewareBackend): string {\n return deployM(backend.purpose)\n}\n","/** 只读部署预检;inspectRemote 仅通过 SSH 读取成功基线,不执行目标写入。 */\nimport type { DeployConfigInput } from './deploy-config.js'\nimport type { DeployAppOptions } from './deploy-types.js'\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { err, ok } from '@h-ai/core'\nimport { z } from 'zod'\nimport { planSidecars, resolveSidecarOptions } from './container/deploy-container-compose.js'\nimport { shellArgument } from './container/deploy-scripts.js'\nimport { createSshExecutor } from './container/deploy-ssh.js'\nimport { DeploymentArtifactSchema, readDeploymentArtifact } from './deploy-artifact.js'\nimport { DeployConfigSchema } from './deploy-config.js'\nimport { loadDeploymentEnvironment } from './deploy-environment.js'\nimport { normalizeProjectName, resolveArtifactDirectory, resolveProjectDirectory, usesDefaultMiddleware } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { scanApp } from './deploy-scanner.js'\nimport { HaiDeployError } from './deploy-types.js'\n\n/**\n * 查看与执行入口相同的扫描、环境、项目身份和制品校验结果。远端 current 只报告为待执行时核验。\n * 输出 root 是工程根,serviceDir 是读取运行配置、扫描依赖的部署服务目录。\n * @example\n * ```ts\n * import { createDeploymentPlan } from '@h-ai/deploy'\n * const plan = await createDeploymentPlan('/workspace/shop', { provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } }, { environment: 'prod' })\n * ```\n */\nexport async function createDeploymentPlan(appDir: string, input: DeployConfigInput, options: DeployAppOptions & { inspectRemote?: boolean } = {}) {\n if ('projectName' in options && options.projectName !== undefined)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_projectNameOverrideRemoved'))\n const parsed = DeployConfigSchema.safeParse(input)\n if (!parsed.success)\n return err({ ...HaiDeployError.CONFIG_ERROR, message: deployM('deploy_artifactInvalid'), ext: { fields: parsed.error.issues.map(issue => issue.path.join('.')) } })\n const config = parsed.data\n const scan = await scanApp(appDir, { environment: options.environment ?? config.environment, envDir: options.envDir })\n if (!scan.success)\n return scan\n const app = scan.data\n const directory = app.appDir ?? appDir\n const environment = await loadDeploymentEnvironment({ environment: options.environment ?? config.environment ?? 'prod', envDir: app.envDir ?? directory, requireFile: true })\n if (!environment.success)\n return environment\n const root = resolveProjectDirectory(directory)\n const projectName = normalizeProjectName(`${normalizeProjectName(app.appName)}${options.environment ?? config.environment ? `-${environment.data.environment}` : ''}`)\n const provider = config.provider\n try {\n let artifactDir = options.artifactDir ?? resolveArtifactDirectory(directory)\n if (existsSync(join(artifactDir, 'latest'))) {\n const latest = readFileSync(join(artifactDir, 'latest'), 'utf8').trim()\n if (!/^[a-z0-9][\\w.+-]*$/i.test(latest))\n throw new Error('Invalid pointer')\n artifactDir = join(artifactDir, latest)\n }\n const artifact = provider.type === 'docker-ssh' ? await readDeploymentArtifact(artifactDir) : undefined\n let images: string[]\n if (artifact) {\n images = [...new Set([artifact.primaryService, ...(artifact.hasWeb ? ['web'] : [])])]\n }\n else {\n // 平台部署没有 OCI 制品时,仍使用工程显式声明的角色,不能把静态或 SSR 站点改叫后端。\n const file = join(root, 'hai.json')\n const project = existsSync(file)\n ? z.object({ build: z.object({ images: z.array(z.object({ name: DeploymentArtifactSchema.shape.primaryService })).min(1).max(2).refine(items => new Set(items.map(item => item.name)).size === items.length).optional() }).optional() }).parse(JSON.parse(readFileSync(file, 'utf8')))\n : undefined\n images = project?.build?.images?.map(image => image.name) ?? [app.isSvelteKit ? 'web' : 'serv']\n }\n const middlewares = (app.middlewares ?? []).filter(item => !['sqlite', 'local', 'memory', 'disabled', 'console', 'lancedb'].includes(item.backend))\n const available = [...new Set([...images, ...app.requiredServices])]\n const selected = [...(options.selectedServices ?? (artifact?.partial ? artifact.images.map(image => image.name) : available))]\n if (!selected.length || new Set(selected).size !== selected.length || selected.some(name => !available.includes(name)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n if (artifact && selected.some(name => images.includes(name) && !artifact.images.some(image => image.name === name)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n const remoteDirectory = provider.type === 'docker-ssh' ? `${provider.remote.baseDir}/${projectName}` : undefined\n const baseline = { required: Boolean(artifact?.partial || options.selectedServices), state: 'not-inspected', current: remoteDirectory ? `${remoteDirectory}/current` : undefined, release: undefined as string | undefined }\n if (options.inspectRemote) {\n if (provider.type !== 'docker-ssh' || !provider.ssh || !remoteDirectory)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n // 仅读取 current 和成功发布目录;不能创建目录、锁、凭据或触发恢复。\n const command = `root=${shellArgument(remoteDirectory)}; if [ -f \"$root/current\" ]; then id=$(head -c 129 \"$root/current\"); case \"$id\" in ''|*[!a-zA-Z0-9._-]*) exit 2;; esac; test -f \"$root/releases/$id/compose-files\" || exit 3; printf '%s' \"$id\"; fi`\n const result = await createSshExecutor(provider.ssh).exec(command, { timeoutMs: 15000, maxCaptureChars: 1024 })\n if (!result.success) {\n baseline.state = 'unavailable'\n }\n else {\n const release = result.data.stdout.trim()\n if (release && !/^[\\w.-]{1,128}$/.test(release))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n baseline.state = release ? 'verified' : 'missing'\n baseline.release = release || undefined\n }\n }\n const configFiles = ['.env', '.env.local', `.env.${environment.data.environment}`, `.env.${environment.data.environment}.local`].map(name => join(environment.data.envDir, name)).filter(existsSync)\n const configDirectory = join(directory, 'config')\n if (existsSync(configDirectory))\n configFiles.push(...readdirSync(configDirectory, { withFileTypes: true }).filter(entry => entry.isFile() && /\\.ya?ml$/i.test(entry.name)).map(entry => join(configDirectory, entry.name)).sort())\n const serviceModes = { ...(options.skipMiddleware ? {} : options.serviceModes), ...Object.fromEntries(app.requiredServices.filter(service => options.skipMiddleware || !selected.includes(service)).map(service => [service, 'keep' as const])) }\n const effective = resolveSidecarOptions(app, { ...options, selectedServices: selected, serviceModes })\n // 只标记将由 Provisioner 提供的配置,不认证、不请求云资源,也不读取或创建本地凭据。\n const provisionKeys = { db: 'HAI_DB', cache: 'HAI_CACHE', storage: 'HAI_STORAGE', email: 'HAI_REACH_PROVIDERS', sms: 'HAI_REACH_PROVIDERS' } as const\n const provisionEnv: Record<string, string> = {}\n const provisioners = new Map<string, string>()\n for (const service of Object.keys(provisionKeys) as Array<keyof typeof provisionKeys>) {\n const provisioner = config.services?.[service]\n if (provisioner && !options.skipMiddleware && usesDefaultMiddleware(app, service, { ...options, serviceModes })) {\n provisionEnv[provisionKeys[service]] = 'planned'\n provisioners.set(service, provisioner.provisioner)\n }\n }\n const sidecar = provider.type === 'docker-ssh' ? planSidecars(directory, projectName, app, provisionEnv, effective, config.container?.s3Engine, { dbPassword: '', storagePassword: '', ldapPassword: '' }) : undefined\n const https = provider.type === 'docker-ssh' ? provider.expose.https : undefined\n const gateway = !!artifact && !(artifact.primaryService === 'serv' && artifact.hasWeb)\n && (sidecar?.services.includes('storage') || (!!https && (artifact.primaryService === 'serv' || app.isSvelteKit)))\n if (gateway && artifact.primaryService === 'web' && !app.isSvelteKit)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageBackendRequired'))\n if (gateway) {\n available.push('gateway')\n if (!baseline.required)\n selected.push('gateway')\n }\n if (https?.type === 'letsencrypt') {\n available.push('certbot')\n if (!baseline.required)\n selected.push('certbot')\n }\n const services = Object.entries(sidecar?.composeServices ?? {}).filter(([name]) => selected.includes(name))\n return ok({\n projectName,\n root,\n serviceDir: directory,\n environment: environment.data.environment,\n target: provider.type === 'docker-ssh' ? { provider: provider.type, host: provider.ssh?.host, port: provider.ssh?.port, directory: remoteDirectory, runtime: provider.remote.runtime, hostPort: provider.expose.hostPort, https: https ? { type: https.type, domain: https.domain, port: https.port } : undefined } : { provider: provider.type },\n artifact: artifact ? { directory: artifactDir, version: artifact.appVersion, buildId: artifact.buildId, verified: true, images: artifact.images.map(image => ({ name: image.name, reference: image.imageRef, sha256: image.sha256 })) } : undefined,\n selected,\n retained: available.filter(name => !selected.includes(name)),\n containers: provider.type === 'docker-ssh' ? [...selected.filter(name => images.includes(name) || name === 'gateway').map(name => `hai-${projectName}-${name}`), ...services.flatMap(([, service]) => typeof service.container_name === 'string' ? [service.container_name] : [])] : [],\n composeManagedServices: [...services.filter(([, service]) => typeof service.container_name !== 'string').map(([name]) => name), ...(selected.includes('certbot') ? ['certbot'] : [])],\n logicalVolumes: Object.keys(sidecar?.volumes ?? {}),\n middleware: middlewares.map(item => ({ service: item.service, backend: item.backend, configuration: item.envPrefix, action: selected.includes(item.service) ? effective.serviceModes?.[item.envPrefix] ?? effective.serviceModes?.[item.service] ?? 'default' : 'keep', provisioner: provisioners.get(item.service) })),\n configuration: { files: [join(root, 'hai.json'), ...configFiles].filter(existsSync), environmentKeys: Object.keys(environment.data.values).sort() },\n baseline,\n recovery: { releases: remoteDirectory ? `${remoteDirectory}/releases` : undefined, point: baseline.release ?? 'previous-successful-release', preservesVolumes: true, databaseRollback: false },\n })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n }\n}\n","/** 旧部署凭据的显式、只读预检与原子导入;不轮换密码、不变更容器和数据卷。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, lstatSync, readFileSync, realpathSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { err, ok } from '@h-ai/core'\nimport { z } from 'zod'\nimport { runCommand } from './container/deploy-command.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst nameSchema = z.string().regex(/^[a-z0-9][\\w.-]{0,127}$/i)\nconst passwordSchema = z.string().min(1).max(1024).refine(value => Buffer.from(value, 'utf8').toString('utf8') === value && [...value].every(character => character.codePointAt(0)! >= 32 && character.codePointAt(0) !== 127))\nconst importSchema = z.strictObject({\n version: z.literal(1),\n projectName: nameSchema,\n credentials: z.strictObject({ DB_PASSWORD: passwordSchema.optional(), STORAGE_PASSWORD: passwordSchema.optional(), LDAP_PASSWORD: passwordSchema.optional() }),\n services: z.array(z.strictObject({\n service: z.enum(['db', 'vecdb', 'storage', 'ldap']),\n container: nameSchema,\n kind: z.enum(['postgresql', 'mysql', 's3', 'ldap']),\n volumes: z.array(nameSchema).min(1).max(8),\n username: z.string().min(1).max(128).default('hai'),\n database: z.string().min(1).max(128).default('hai'),\n bucket: z.string().regex(/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/).default('hai'),\n accessKeyId: z.string().min(1).max(128).default('hai-storage'),\n region: z.string().regex(/^[a-z0-9-]+$/).default('us-east-1'),\n bindDn: z.string().min(1).max(512).default('cn=admin,dc=example,dc=org'),\n })).min(1).max(4),\n})\nconst groups = { db: 'DB_PASSWORD', vecdb: 'DB_PASSWORD', storage: 'STORAGE_PASSWORD', ldap: 'LDAP_PASSWORD' } as const\n\n/** 独立持锁进程只接受完整状态,原子发布并同步目录;中断时留下的私有 next 文件不被后续导入信任。 */\nconst importCommitScript = String.raw`(async()=>{const fs=require('node:fs'),path=require('node:path'),crypto=require('node:crypto');const root=process.argv[1];let temporary;\ntry{process.stdout.write('LOCKED\\n');let input='';for await(const chunk of process.stdin){input+=chunk;if(input.length>65536)throw Error()}\nif(!input)return;const {content}=JSON.parse(input);if(typeof content!=='string'||!content.startsWith('FORMAT_VERSION=2\\n'))throw Error();\nconst state=path.join(root,'managed-secrets.env');try{fs.lstatSync(state);throw Error('exists')}catch(error){if(error.code!=='ENOENT')throw error}\ntemporary=path.join(root,'.managed-secrets-'+crypto.randomUUID()+'.next');const fd=fs.openSync(temporary,fs.constants.O_WRONLY|fs.constants.O_CREAT|fs.constants.O_EXCL|fs.constants.O_NOFOLLOW,0o600);\ntry{fs.writeFileSync(fd,content);fs.fsyncSync(fd)}finally{fs.closeSync(fd)}fs.renameSync(temporary,state);temporary=undefined;\nconst directory=fs.openSync(root,fs.constants.O_RDONLY);try{fs.fsyncSync(directory)}finally{fs.closeSync(directory)}process.stdout.write('COMMITTED\\n');\n}catch{process.exitCode=1}finally{if(temporary)try{fs.unlinkSync(temporary)}catch{}}})()`\n\n/** 仅在同项目的现有 Node 应用容器中执行 S3 HEAD;不写配置,不跟随重定向,不输出服务响应。 */\nconst s3VerificationScript = String.raw`(async()=>{try{\nconst {createHash,createHmac}=require('node:crypto');let input='';for await(const chunk of process.stdin)input+=chunk;\nconst {endpoint,bucket,accessKeyId,secret,region}=JSON.parse(input);const url=new URL('/'+encodeURIComponent(bucket),endpoint);\nconst hash=value=>createHash('sha256').update(value).digest('hex');const hmac=(key,value)=>createHmac('sha256',key).update(value).digest();\nconst date=new Date().toISOString().replace(/[:-]|\\.\\d{3}/g,'');const day=date.slice(0,8);const payload=hash('');\nconst headers='host:'+url.host+'\\nx-amz-content-sha256:'+payload+'\\nx-amz-date:'+date+'\\n';const signed='host;x-amz-content-sha256;x-amz-date';\nconst scope=day+'/'+region+'/s3/aws4_request';const canonical=['HEAD',url.pathname,'',headers,signed,payload].join('\\n');\nconst key=hmac(hmac(hmac(hmac('AWS4'+secret,day),region),'s3'),'aws4_request');const signature=hmac(key,['AWS4-HMAC-SHA256',date,scope,hash(canonical)].join('\\n')).toString('hex');\nconst response=await fetch(url,{method:'HEAD',redirect:'manual',signal:AbortSignal.timeout(10000),headers:{'x-amz-date':date,'x-amz-content-sha256':payload,Authorization:'AWS4-HMAC-SHA256 Credential='+accessKeyId+'/'+scope+', SignedHeaders='+signed+', Signature='+signature}});\nawait response.body?.cancel();if(response.ok)process.stdout.write('VERIFIED');else process.exitCode=1;\n}catch{process.exitCode=1}})()`\n\n/**\n * 在目标服务器导入前核验旧凭据;dryRun 默认 true,apply 需要 Linux flock 与运行中的原服务。\n * 输入文件必须由操作者明确指定,权限 0600;API 不读取旧部署包猜测密码。\n * @param options - 服务器项目目录、受保护的导入 JSON、容器引擎和只读开关。\n * @param options.directory - 目标 Linux 服务器上已存在的项目部署目录。\n * @param options.inputFile - 操作者提供的版本化私有 JSON 文件路径。\n * @param options.runtime - 实际使用的 Docker 或 Podman 引擎。\n * @param options.dryRun - 默认 true;只有显式 false 才在部署锁内保存状态。\n * @returns 仅包含项目、凭据组和卷名的回执,不包含密码;失败不推进 current 或改变服务。\n * @example\n * ```ts\n * import { importDeploymentSecrets } from '@h-ai/deploy'\n * const plan = await importDeploymentSecrets({ directory: '/opt/hai/apps/shop-test', inputFile: '/private/shop-import.json', runtime: 'docker' })\n * if (!plan.success) throw new Error(plan.error.message)\n * // 停止业务写入、备份数据后,用相同输入显式传 dryRun: false 导入。\n * ```\n */\nexport async function importDeploymentSecrets(options: {\n directory: string\n inputFile: string\n runtime: 'docker' | 'podman'\n dryRun?: boolean\n}): Promise<HaiResult<{ projectName: string, stateVersion: 2, groups: string[], volumes: string[], changed: boolean }>> {\n let lock: Awaited<ReturnType<typeof acquireImportLock>> | undefined\n let commitAttempted = false\n let phase: 'input' | 'identity' | 'verification' | 'lock' | 'state' = 'input'\n try {\n if (!['docker', 'podman'].includes(options.runtime))\n throw new Error('input')\n const root = resolve(options.directory)\n if (realpathSync(root) !== root || !lstatSync(root).isDirectory() || (process.platform !== 'win32' && (lstatSync(root).mode & 0o022)))\n throw new Error('input')\n const input = privateFile(resolve(options.inputFile))\n const parsed = importSchema.safeParse(JSON.parse(input))\n if (!parsed.success)\n return err({ ...HaiDeployError.CONFIG_ERROR, message: deployM('deploy_secretImportFailed', { params: { phase } }), ext: { phase, state: 'unchanged', fields: parsed.error.issues.map(issue => issue.path.join('.')) } })\n const config = parsed.data\n const project = `hai-${config.projectName}`\n const selectedGroups = [...new Set(config.services.map(service => groups[service.service]))].sort()\n if (new Set(config.services.map(service => service.service)).size !== config.services.length\n || Object.keys(config.credentials).some(group => !selectedGroups.includes(group as typeof selectedGroups[number]))\n || selectedGroups.some(group => !config.credentials[group])) {\n throw new Error('input')\n }\n const secrets = Object.values(config.credentials).filter((value): value is string => typeof value === 'string')\n const stateFile = join(root, 'managed-secrets.env')\n const lockFile = join(root, '.deploy.lock')\n phase = 'lock'\n if (options.dryRun === false) {\n if (process.platform !== 'linux')\n throw new Error('lock')\n if (existsSync(lockFile) && (lstatSync(lockFile).isSymbolicLink() || !lstatSync(lockFile).isFile() || lstatSync(lockFile).nlink !== 1))\n throw new Error('lock')\n lock = await acquireImportLock(lockFile, root)\n }\n phase = 'identity'\n const volumes: Array<{ group: string, name: string }> = []\n for (const service of config.services) {\n const kindValid = service.service === 'storage' ? service.kind === 's3' : service.service === 'ldap' ? service.kind === 'ldap' : ['postgresql', 'mysql'].includes(service.kind)\n if (!kindValid)\n throw new Error('identity')\n // 受管 sidecar 固定账户/库/桶身份;不能只导入密码后让后续部署悄悄切换身份。\n if ((['postgresql', 'mysql'].includes(service.kind) && (service.username !== 'hai' || service.database !== 'hai'))\n || (service.kind === 's3' && (service.accessKeyId !== 'hai-storage' || service.bucket !== 'hai' || service.region !== 'us-east-1'))\n || (service.kind === 'ldap' && service.bindDn !== 'cn=admin,dc=example,dc=org')) {\n throw new Error('identity')\n }\n const identity = await inspectContainer(options.runtime, service.container, secrets)\n if (identity.project !== project || identity.service !== service.service || !identity.running)\n throw new Error('identity')\n for (const volume of service.volumes) {\n if (!identity.volumes.includes(volume))\n throw new Error('identity')\n volumes.push({ group: groups[service.service], name: volume })\n }\n phase = 'verification'\n const password = config.credentials[groups[service.service]]!\n let verified = false\n if (service.kind === 's3') {\n const helper = `hai-${config.projectName}-app`\n const application = await inspectContainer(options.runtime, helper, secrets)\n if (application.project !== project || application.service !== 'app' || !application.running || !application.networks.some(network => identity.networks.includes(network)))\n throw new Error('identity')\n const result = await runCommand(options.runtime, ['exec', '-i', helper, 'node', '-e', s3VerificationScript], { input: JSON.stringify({ endpoint: `http://${service.container}:9000`, bucket: service.bucket, accessKeyId: service.accessKeyId, secret: password, region: service.region }), secrets, timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = result.success && result.data.stdout.trim() === 'VERIFIED'\n }\n else {\n const args = service.kind === 'ldap'\n ? ['exec', '-i', service.container, 'ldapwhoami', '-x', '-H', 'ldap://127.0.0.1:389', '-D', service.bindDn, '-y', '/dev/stdin']\n : ['exec', '-i', service.container, 'sh', '-c', service.kind === 'postgresql'\n ? 'IFS= read -r PGPASSWORD; export PGPASSWORD; exec psql --no-psqlrc -h \"$3\" -U \"$1\" -d \"dbname=$2 require_auth=scram-sha-256,md5,password\" -Atc \"SELECT 1\"'\n : 'IFS= read -r MYSQL_PWD; export MYSQL_PWD; exec mysql -h 127.0.0.1 -u \"$1\" \"$2\" -Nse \"SELECT 1\"', 'hai-secret-check', service.username, service.database, service.container]\n // LDAP -y 按文件字节读取密码,不能附加 shell read 使用的行尾。\n const result = await runCommand(options.runtime, args, { input: service.kind === 'ldap' ? password : `${password}\\n`, secrets, timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = result.success && !result.data.stdoutTruncated && (service.kind === 'ldap' ? result.data.stdout.trim().startsWith('dn:') : result.data.stdout.trim() === '1')\n if (verified && service.kind === 'mysql') {\n const rootCheck = await runCommand(options.runtime, [...args.slice(0, -3), 'root', service.database, service.container], { input: `${password}\\n`, secrets, timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = rootCheck.success && !rootCheck.data.stdoutTruncated && rootCheck.data.stdout.trim() === '1'\n // MySQL 的各版本不统一暴露 skip_grant_tables;实际错误密码必须收到认证拒绝。\n const invalidPassword = `hai-import-invalid-${randomUUID()}`\n for (const username of [service.username, 'root']) {\n if (!verified)\n break\n const negative = await runCommand(options.runtime, [...args.slice(0, -3), username, service.database, service.container], { input: `${invalidPassword}\\n`, secrets: [...secrets, invalidPassword], timeoutMs: 15000, maxCaptureChars: 1024 })\n verified = !negative.success && /ERROR 1045 \\(28000\\)/.test(negative.error.message)\n }\n }\n }\n if (!verified)\n throw new Error('verification')\n phase = 'identity'\n }\n phase = 'state'\n const uniqueVolumes = [...new Map(volumes.map(volume => [`${volume.group}:${volume.name}`, volume])).values()].sort((a, b) => `${a.group}:${a.name}`.localeCompare(`${b.group}:${b.name}`))\n const lines = ['FORMAT_VERSION=2', `PROJECT=${project}`, ...selectedGroups.map(group => `${group}=${Buffer.from(config.credentials[group]!, 'utf8').toString('hex')}`), ...uniqueVolumes.map((volume, index) => `VOLUME_${index + 1}=${volume.group}:${volume.name}`)]\n let changed = false\n if (existsSync(stateFile) || isSymbolicLink(stateFile)) {\n const existing = readImportedState(privateFile(stateFile))\n if (existing.FORMAT_VERSION !== '2' || existing.PROJECT !== project || selectedGroups.some(group => existing[group] !== Buffer.from(config.credentials[group]!, 'utf8').toString('hex')) || uniqueVolumes.some(volume => !Object.entries(existing).some(([key, value]) => /^VOLUME_\\d+$/.test(key) && value === `${volume.group}:${volume.name}`)))\n throw new Error('state')\n }\n else if (options.dryRun === false) {\n commitAttempted = true\n if (!lock || !await lock.commit(`${lines.join('\\n')}\\n`))\n throw new Error('lock')\n changed = true\n }\n return ok({ projectName: config.projectName, stateVersion: 2, groups: selectedGroups, volumes: uniqueVolumes.map(volume => volume.name), changed })\n }\n catch {\n return err({ ...HaiDeployError.CONFIG_ERROR, message: deployM('deploy_secretImportFailed', { params: { phase } }), ext: { phase, state: commitAttempted ? 'unknown' : 'unchanged' } })\n }\n finally {\n await lock?.release()\n }\n}\n\nfunction readImportedState(text: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of text.trimEnd().split('\\n')) {\n const match = /^(FORMAT_VERSION|PROJECT|DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD|VOLUME_[1-9]\\d*)=([^=]+)$/.exec(line)\n if (!match || Object.hasOwn(result, match[1]!))\n throw new Error('state')\n const key = match[1]!\n const value = match[2]!\n if (key.endsWith('_PASSWORD')) {\n if (!/^(?:[a-f0-9]{2})+$/.test(value))\n throw new Error('state')\n const decoded = Buffer.from(value, 'hex').toString('utf8')\n if (!passwordSchema.safeParse(decoded).success || Buffer.from(decoded, 'utf8').toString('hex') !== value)\n throw new Error('state')\n }\n else if (key.startsWith('VOLUME_') && !/^(?:DB_PASSWORD|STORAGE_PASSWORD|LDAP_PASSWORD):[a-zA-Z0-9][\\w.-]*$/.test(value)) {\n throw new Error('state')\n }\n result[key] = value\n }\n if (result.FORMAT_VERSION !== '2' || !nameSchema.safeParse(result.PROJECT).success)\n throw new Error('state')\n return result\n}\n\nfunction isSymbolicLink(path: string): boolean {\n try {\n return lstatSync(path).isSymbolicLink()\n }\n catch {\n return false\n }\n}\n\nfunction privateFile(path: string): string {\n const stat = lstatSync(path)\n if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1 || stat.size > 65536 || (process.platform !== 'win32' && ((stat.mode & 0o077) || (process.getuid?.() !== 0 && stat.uid !== process.getuid?.()))))\n throw new Error('private-file')\n return readFileSync(path, 'utf8')\n}\n\nasync function inspectContainer(runtime: string, container: string, secrets: string[]) {\n const result = await runCommand(runtime, ['inspect', '--format', '{{json .Config.Labels}}\\n{{json .Mounts}}\\n{{json .State.Running}}\\n{{json .NetworkSettings.Networks}}', container], { secrets, timeoutMs: 10000, maxCaptureChars: 32768 })\n if (!result.success || result.data.stdoutTruncated)\n throw new Error('identity')\n const [labelsText, mountsText, runningText, networksText] = result.data.stdout.trim().split('\\n')\n const labels = z.record(z.string(), z.string()).parse(JSON.parse(labelsText!))\n const mounts = z.array(z.object({ Type: z.string(), Name: z.string().optional() })).parse(JSON.parse(mountsText!))\n // Podman 的默认 pasta/slirp 网络可返回 null;原生 DB/LDAP 验证不要求命名网络。\n const networks = z.record(z.string(), z.object({ NetworkID: z.string() })).parse(JSON.parse(networksText!) ?? {})\n // 每种已声明的标准标签必须完整,两个命名空间同时声明时保持一致,禁止混拼身份。\n const dockerProject = labels['com.docker.compose.project'] || undefined\n const podmanProject = labels['io.podman.compose.project'] || undefined\n const dockerService = labels['com.docker.compose.service'] || undefined\n const podmanService = labels['io.podman.compose.service'] || undefined\n if (Boolean(dockerProject) !== Boolean(dockerService) || Boolean(podmanProject) !== Boolean(podmanService)\n || (dockerProject && podmanProject && dockerProject !== podmanProject) || (dockerService && podmanService && dockerService !== podmanService)) {\n throw new Error('identity')\n }\n return { project: dockerProject ?? podmanProject, service: dockerService ?? podmanService, running: runningText === 'true', volumes: mounts.flatMap(mount => mount.Type === 'volume' && mount.Name ? [mount.Name] : []), networks: Object.values(networks).map(network => network.NetworkID) }\n}\n\n/** flock 子进程持有同一个固定锁文件;父进程消失后 stdin 关闭,自然释放锁。 */\nasync function acquireImportLock(path: string, root: string): Promise<{ commit: (content: string) => Promise<boolean>, release: () => Promise<void> }> {\n return new Promise((resolveLock, reject) => {\n // 最终写入也由持锁进程完成;锁 helper 意外退出时父进程无法越过锁提交。\n const child = spawn('flock', ['-n', path, process.execPath, '-e', importCommitScript, root], { stdio: ['pipe', 'pipe', 'ignore'], windowsHide: true })\n let acquired = false\n let exited = false\n let output = ''\n const finished = new Promise<void>(done => child.once('close', () => {\n exited = true\n done()\n }))\n child.stdin.on('error', () => { /* 由提交回执判断失败,不泄漏输入。 */ })\n const timer = setTimeout(() => {\n child.stdin.end()\n child.kill()\n reject(new Error('lock'))\n }, 5000)\n child.once('error', () => {\n clearTimeout(timer)\n reject(new Error('lock'))\n })\n child.once('exit', () => {\n if (!acquired) {\n clearTimeout(timer)\n reject(new Error('lock'))\n }\n })\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString()\n if (acquired || !output.includes('\\n'))\n return\n if (!output.startsWith('LOCKED\\n') || exited) {\n child.stdin.end()\n reject(new Error('lock'))\n return\n }\n acquired = true\n clearTimeout(timer)\n resolveLock({\n commit: async (content) => {\n if (exited)\n return false\n child.stdin.end(JSON.stringify({ content }))\n await finished\n return child.exitCode === 0 && output === 'LOCKED\\nCOMMITTED\\n'\n },\n release: async () => {\n child.stdin.end()\n await finished\n },\n })\n })\n })\n}\n"]}
|