ysk-server-core 1.0.0 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (627) hide show
  1. package/README.md +23 -6
  2. package/dist/agents/probe.d.ts +2 -0
  3. package/dist/agents/probe.d.ts.map +1 -1
  4. package/dist/agents/probe.js +58 -1
  5. package/dist/agents/probe.js.map +1 -1
  6. package/dist/db/database.d.ts +1 -1
  7. package/dist/db/database.js +1 -1
  8. package/dist/db/document-store.d.ts +6 -2
  9. package/dist/db/document-store.d.ts.map +1 -1
  10. package/dist/db/document-store.js +5 -5
  11. package/dist/db/document-store.js.map +1 -1
  12. package/dist/db/store.d.ts +31 -2
  13. package/dist/db/store.d.ts.map +1 -1
  14. package/dist/db/store.js +286 -40
  15. package/dist/db/store.js.map +1 -1
  16. package/dist/email/autodiscover.d.ts +3 -0
  17. package/dist/email/autodiscover.d.ts.map +1 -1
  18. package/dist/email/autodiscover.js +57 -17
  19. package/dist/email/autodiscover.js.map +1 -1
  20. package/dist/email/dns-records.d.ts.map +1 -1
  21. package/dist/email/dns-records.js +3 -1
  22. package/dist/email/dns-records.js.map +1 -1
  23. package/dist/email/live-checks.d.ts.map +1 -1
  24. package/dist/email/live-checks.js +13 -4
  25. package/dist/email/live-checks.js.map +1 -1
  26. package/dist/email/mail-queue.d.ts +13 -4
  27. package/dist/email/mail-queue.d.ts.map +1 -1
  28. package/dist/email/mail-queue.js +69 -14
  29. package/dist/email/mail-queue.js.map +1 -1
  30. package/dist/email/mail-tls-apply.d.ts.map +1 -1
  31. package/dist/email/mail-tls-apply.js +22 -0
  32. package/dist/email/mail-tls-apply.js.map +1 -1
  33. package/dist/files/index.d.ts +1 -0
  34. package/dist/files/index.d.ts.map +1 -1
  35. package/dist/files/index.js +1 -0
  36. package/dist/files/index.js.map +1 -1
  37. package/dist/files/manager.d.ts +25 -6
  38. package/dist/files/manager.d.ts.map +1 -1
  39. package/dist/files/manager.js +166 -33
  40. package/dist/files/manager.js.map +1 -1
  41. package/dist/files/name-conflict.d.ts +9 -0
  42. package/dist/files/name-conflict.d.ts.map +1 -0
  43. package/dist/files/name-conflict.js +36 -0
  44. package/dist/files/name-conflict.js.map +1 -0
  45. package/dist/files/shares.d.ts.map +1 -1
  46. package/dist/files/shares.js +17 -1
  47. package/dist/files/shares.js.map +1 -1
  48. package/dist/host/executor.d.ts +3 -0
  49. package/dist/host/executor.d.ts.map +1 -1
  50. package/dist/host/executor.js +169 -7
  51. package/dist/host/executor.js.map +1 -1
  52. package/dist/host-browse/browser-engine.d.ts.map +1 -1
  53. package/dist/host-browse/browser-engine.js +2 -1
  54. package/dist/host-browse/browser-engine.js.map +1 -1
  55. package/dist/host-browse/chrome-as-user.d.ts.map +1 -1
  56. package/dist/host-browse/chrome-as-user.js +2 -1
  57. package/dist/host-browse/chrome-as-user.js.map +1 -1
  58. package/dist/host-browse/chrome-path.d.ts +13 -0
  59. package/dist/host-browse/chrome-path.d.ts.map +1 -0
  60. package/dist/host-browse/chrome-path.js +76 -0
  61. package/dist/host-browse/chrome-path.js.map +1 -0
  62. package/dist/host-browse/chrome-probe.d.ts.map +1 -1
  63. package/dist/host-browse/chrome-probe.js +3 -2
  64. package/dist/host-browse/chrome-probe.js.map +1 -1
  65. package/dist/host-browse/index.d.ts +1 -0
  66. package/dist/host-browse/index.d.ts.map +1 -1
  67. package/dist/host-browse/index.js +1 -0
  68. package/dist/host-browse/index.js.map +1 -1
  69. package/dist/host-browse/ssrf.d.ts.map +1 -1
  70. package/dist/host-browse/ssrf.js +2 -2
  71. package/dist/host-browse/ssrf.js.map +1 -1
  72. package/dist/host-browse/types.d.ts.map +1 -1
  73. package/dist/host-browse/types.js +4 -3
  74. package/dist/host-browse/types.js.map +1 -1
  75. package/dist/hosting/apache/render-site.d.ts.map +1 -1
  76. package/dist/hosting/apache/render-site.js +2 -1
  77. package/dist/hosting/apache/render-site.js.map +1 -1
  78. package/dist/hosting/apache/sync.d.ts +2 -0
  79. package/dist/hosting/apache/sync.d.ts.map +1 -1
  80. package/dist/hosting/apache/sync.js +25 -0
  81. package/dist/hosting/apache/sync.js.map +1 -1
  82. package/dist/hosting/app-templates.js +1 -1
  83. package/dist/hosting/app-templates.js.map +1 -1
  84. package/dist/hosting/backup-cron.d.ts +44 -1
  85. package/dist/hosting/backup-cron.d.ts.map +1 -1
  86. package/dist/hosting/backup-cron.js +432 -39
  87. package/dist/hosting/backup-cron.js.map +1 -1
  88. package/dist/hosting/backup-remote.d.ts +17 -0
  89. package/dist/hosting/backup-remote.d.ts.map +1 -1
  90. package/dist/hosting/backup-remote.js +341 -55
  91. package/dist/hosting/backup-remote.js.map +1 -1
  92. package/dist/hosting/bt-tracker/index.d.ts +3 -0
  93. package/dist/hosting/bt-tracker/index.d.ts.map +1 -1
  94. package/dist/hosting/bt-tracker/index.js +3 -0
  95. package/dist/hosting/bt-tracker/index.js.map +1 -1
  96. package/dist/hosting/bt-tracker/library-ops.d.ts +86 -0
  97. package/dist/hosting/bt-tracker/library-ops.d.ts.map +1 -0
  98. package/dist/hosting/bt-tracker/library-ops.js +481 -0
  99. package/dist/hosting/bt-tracker/library-ops.js.map +1 -0
  100. package/dist/hosting/bt-tracker/library.d.ts +12 -0
  101. package/dist/hosting/bt-tracker/library.d.ts.map +1 -0
  102. package/dist/hosting/bt-tracker/library.js +109 -0
  103. package/dist/hosting/bt-tracker/library.js.map +1 -0
  104. package/dist/hosting/bt-tracker/restore-library.d.ts +16 -0
  105. package/dist/hosting/bt-tracker/restore-library.d.ts.map +1 -0
  106. package/dist/hosting/bt-tracker/restore-library.js +67 -0
  107. package/dist/hosting/bt-tracker/restore-library.js.map +1 -0
  108. package/dist/hosting/bt-tracker/restore-shares.d.ts.map +1 -1
  109. package/dist/hosting/bt-tracker/restore-shares.js +8 -0
  110. package/dist/hosting/bt-tracker/restore-shares.js.map +1 -1
  111. package/dist/hosting/bt-tracker/seeder.d.ts +55 -16
  112. package/dist/hosting/bt-tracker/seeder.d.ts.map +1 -1
  113. package/dist/hosting/bt-tracker/seeder.js +103 -3
  114. package/dist/hosting/bt-tracker/seeder.js.map +1 -1
  115. package/dist/hosting/bt-tracker/service.d.ts.map +1 -1
  116. package/dist/hosting/bt-tracker/service.js +28 -4
  117. package/dist/hosting/bt-tracker/service.js.map +1 -1
  118. package/dist/hosting/bt-tracker/settings.d.ts +14 -1
  119. package/dist/hosting/bt-tracker/settings.d.ts.map +1 -1
  120. package/dist/hosting/bt-tracker/settings.js +102 -3
  121. package/dist/hosting/bt-tracker/settings.js.map +1 -1
  122. package/dist/hosting/cdn/fan-out.d.ts.map +1 -1
  123. package/dist/hosting/cdn/fan-out.js +64 -32
  124. package/dist/hosting/cdn/fan-out.js.map +1 -1
  125. package/dist/hosting/cdn/from-project.d.ts +6 -0
  126. package/dist/hosting/cdn/from-project.d.ts.map +1 -1
  127. package/dist/hosting/cdn/from-project.js +55 -1
  128. package/dist/hosting/cdn/from-project.js.map +1 -1
  129. package/dist/hosting/cdn/http-probe-error.d.ts +7 -0
  130. package/dist/hosting/cdn/http-probe-error.d.ts.map +1 -0
  131. package/dist/hosting/cdn/http-probe-error.js +44 -0
  132. package/dist/hosting/cdn/http-probe-error.js.map +1 -0
  133. package/dist/hosting/cdn/nodes.d.ts +8 -0
  134. package/dist/hosting/cdn/nodes.d.ts.map +1 -1
  135. package/dist/hosting/cdn/nodes.js +69 -1
  136. package/dist/hosting/cdn/nodes.js.map +1 -1
  137. package/dist/hosting/cdn/sites.d.ts +2 -0
  138. package/dist/hosting/cdn/sites.d.ts.map +1 -1
  139. package/dist/hosting/cdn/sites.js +5 -1
  140. package/dist/hosting/cdn/sites.js.map +1 -1
  141. package/dist/hosting/cdn/ssl.d.ts.map +1 -1
  142. package/dist/hosting/cdn/ssl.js +3 -25
  143. package/dist/hosting/cdn/ssl.js.map +1 -1
  144. package/dist/hosting/db-cluster/apply-local.d.ts +1 -1
  145. package/dist/hosting/db-cluster/apply-local.js +7 -7
  146. package/dist/hosting/db-cluster/apply-local.js.map +1 -1
  147. package/dist/hosting/db-cluster/probe.js +1 -1
  148. package/dist/hosting/db-cluster/probe.js.map +1 -1
  149. package/dist/hosting/db-cluster/push-peer.d.ts +3 -0
  150. package/dist/hosting/db-cluster/push-peer.d.ts.map +1 -1
  151. package/dist/hosting/db-cluster/push-peer.js +41 -21
  152. package/dist/hosting/db-cluster/push-peer.js.map +1 -1
  153. package/dist/hosting/db-cluster/store.d.ts +1 -0
  154. package/dist/hosting/db-cluster/store.d.ts.map +1 -1
  155. package/dist/hosting/db-cluster/store.js +11 -0
  156. package/dist/hosting/db-cluster/store.js.map +1 -1
  157. package/dist/hosting/db-cluster/types.d.ts +1 -1
  158. package/dist/hosting/db-cluster/types.d.ts.map +1 -1
  159. package/dist/hosting/db-service-config.d.ts +13 -0
  160. package/dist/hosting/db-service-config.d.ts.map +1 -1
  161. package/dist/hosting/db-service-config.js +51 -1
  162. package/dist/hosting/db-service-config.js.map +1 -1
  163. package/dist/hosting/defense/automation.js +1 -1
  164. package/dist/hosting/defense/automation.js.map +1 -1
  165. package/dist/hosting/defense/defense-service.d.ts.map +1 -1
  166. package/dist/hosting/defense/defense-service.js +62 -39
  167. package/dist/hosting/defense/defense-service.js.map +1 -1
  168. package/dist/hosting/defense/geoip/index.d.ts.map +1 -1
  169. package/dist/hosting/defense/geoip/index.js +9 -7
  170. package/dist/hosting/defense/geoip/index.js.map +1 -1
  171. package/dist/hosting/defense/presets.js +2 -2
  172. package/dist/hosting/defense/presets.js.map +1 -1
  173. package/dist/hosting/defense/signals.d.ts +5 -0
  174. package/dist/hosting/defense/signals.d.ts.map +1 -1
  175. package/dist/hosting/defense/signals.js +26 -10
  176. package/dist/hosting/defense/signals.js.map +1 -1
  177. package/dist/hosting/defense/types.d.ts +2 -0
  178. package/dist/hosting/defense/types.d.ts.map +1 -1
  179. package/dist/hosting/dns-health.d.ts.map +1 -1
  180. package/dist/hosting/dns-health.js +34 -26
  181. package/dist/hosting/dns-health.js.map +1 -1
  182. package/dist/hosting/dns-lookup.d.ts.map +1 -1
  183. package/dist/hosting/dns-lookup.js +11 -0
  184. package/dist/hosting/dns-lookup.js.map +1 -1
  185. package/dist/hosting/dns-zone.d.ts +18 -0
  186. package/dist/hosting/dns-zone.d.ts.map +1 -1
  187. package/dist/hosting/dns-zone.js +59 -0
  188. package/dist/hosting/dns-zone.js.map +1 -1
  189. package/dist/hosting/docker/argv.d.ts +10 -0
  190. package/dist/hosting/docker/argv.d.ts.map +1 -0
  191. package/dist/hosting/docker/argv.js +274 -0
  192. package/dist/hosting/docker/argv.js.map +1 -0
  193. package/dist/hosting/docker/daemon.d.ts +27 -0
  194. package/dist/hosting/docker/daemon.d.ts.map +1 -0
  195. package/dist/hosting/docker/daemon.js +125 -0
  196. package/dist/hosting/docker/daemon.js.map +1 -0
  197. package/dist/hosting/docker/honesty.d.ts +27 -0
  198. package/dist/hosting/docker/honesty.d.ts.map +1 -0
  199. package/dist/hosting/docker/honesty.js +50 -0
  200. package/dist/hosting/docker/honesty.js.map +1 -0
  201. package/dist/hosting/docker/index.d.ts +6 -0
  202. package/dist/hosting/docker/index.d.ts.map +1 -0
  203. package/dist/hosting/docker/index.js +6 -0
  204. package/dist/hosting/docker/index.js.map +1 -0
  205. package/dist/hosting/docker/manager.d.ts +131 -0
  206. package/dist/hosting/docker/manager.d.ts.map +1 -0
  207. package/dist/hosting/docker/manager.js +681 -0
  208. package/dist/hosting/docker/manager.js.map +1 -0
  209. package/dist/hosting/docker/parse.d.ts +22 -0
  210. package/dist/hosting/docker/parse.d.ts.map +1 -0
  211. package/dist/hosting/docker/parse.js +205 -0
  212. package/dist/hosting/docker/parse.js.map +1 -0
  213. package/dist/hosting/extras.d.ts.map +1 -1
  214. package/dist/hosting/extras.js +7 -1
  215. package/dist/hosting/extras.js.map +1 -1
  216. package/dist/hosting/fail2ban-ops.d.ts +2 -0
  217. package/dist/hosting/fail2ban-ops.d.ts.map +1 -1
  218. package/dist/hosting/fail2ban-ops.js +11 -9
  219. package/dist/hosting/fail2ban-ops.js.map +1 -1
  220. package/dist/hosting/firewall-ops.d.ts +4 -0
  221. package/dist/hosting/firewall-ops.d.ts.map +1 -1
  222. package/dist/hosting/firewall-ops.js +43 -2
  223. package/dist/hosting/firewall-ops.js.map +1 -1
  224. package/dist/hosting/ftps-service.d.ts +34 -0
  225. package/dist/hosting/ftps-service.d.ts.map +1 -1
  226. package/dist/hosting/ftps-service.js +141 -13
  227. package/dist/hosting/ftps-service.js.map +1 -1
  228. package/dist/hosting/git-auth.d.ts +77 -0
  229. package/dist/hosting/git-auth.d.ts.map +1 -0
  230. package/dist/hosting/git-auth.js +314 -0
  231. package/dist/hosting/git-auth.js.map +1 -0
  232. package/dist/hosting/git-control.d.ts +110 -0
  233. package/dist/hosting/git-control.d.ts.map +1 -0
  234. package/dist/hosting/git-control.js +333 -0
  235. package/dist/hosting/git-control.js.map +1 -0
  236. package/dist/hosting/git-deploy.d.ts +2 -0
  237. package/dist/hosting/git-deploy.d.ts.map +1 -1
  238. package/dist/hosting/git-deploy.js +50 -7
  239. package/dist/hosting/git-deploy.js.map +1 -1
  240. package/dist/hosting/git-errors.d.ts +7 -0
  241. package/dist/hosting/git-errors.d.ts.map +1 -0
  242. package/dist/hosting/git-errors.js +45 -0
  243. package/dist/hosting/git-errors.js.map +1 -0
  244. package/dist/hosting/git-hook.d.ts +33 -0
  245. package/dist/hosting/git-hook.d.ts.map +1 -0
  246. package/dist/hosting/git-hook.js +174 -0
  247. package/dist/hosting/git-hook.js.map +1 -0
  248. package/dist/hosting/global-search.d.ts.map +1 -1
  249. package/dist/hosting/global-search.js +22 -4
  250. package/dist/hosting/global-search.js.map +1 -1
  251. package/dist/hosting/host-migrate/bootstrap-target.d.ts +1 -1
  252. package/dist/hosting/host-migrate/bootstrap-target.js +6 -6
  253. package/dist/hosting/host-migrate/bootstrap-target.js.map +1 -1
  254. package/dist/hosting/host-migrate/index.d.ts +1 -0
  255. package/dist/hosting/host-migrate/index.d.ts.map +1 -1
  256. package/dist/hosting/host-migrate/index.js +1 -0
  257. package/dist/hosting/host-migrate/index.js.map +1 -1
  258. package/dist/hosting/host-migrate/inventory.d.ts.map +1 -1
  259. package/dist/hosting/host-migrate/inventory.js +20 -0
  260. package/dist/hosting/host-migrate/inventory.js.map +1 -1
  261. package/dist/hosting/host-migrate/orphan-homes.d.ts +19 -0
  262. package/dist/hosting/host-migrate/orphan-homes.d.ts.map +1 -0
  263. package/dist/hosting/host-migrate/orphan-homes.js +46 -0
  264. package/dist/hosting/host-migrate/orphan-homes.js.map +1 -0
  265. package/dist/hosting/host-migrate/temp-key.d.ts.map +1 -1
  266. package/dist/hosting/host-migrate/temp-key.js +7 -1
  267. package/dist/hosting/host-migrate/temp-key.js.map +1 -1
  268. package/dist/hosting/index.d.ts +9 -0
  269. package/dist/hosting/index.d.ts.map +1 -1
  270. package/dist/hosting/index.js +9 -0
  271. package/dist/hosting/index.js.map +1 -1
  272. package/dist/hosting/leftover-apply.d.ts +34 -0
  273. package/dist/hosting/leftover-apply.d.ts.map +1 -0
  274. package/dist/hosting/leftover-apply.js +187 -0
  275. package/dist/hosting/leftover-apply.js.map +1 -0
  276. package/dist/hosting/leftover-probe.d.ts +40 -0
  277. package/dist/hosting/leftover-probe.d.ts.map +1 -0
  278. package/dist/hosting/leftover-probe.js +181 -0
  279. package/dist/hosting/leftover-probe.js.map +1 -0
  280. package/dist/hosting/log-center/catalog.d.ts.map +1 -1
  281. package/dist/hosting/log-center/catalog.js +9 -0
  282. package/dist/hosting/log-center/catalog.js.map +1 -1
  283. package/dist/hosting/log-center/journal.d.ts.map +1 -1
  284. package/dist/hosting/log-center/journal.js +3 -0
  285. package/dist/hosting/log-center/journal.js.map +1 -1
  286. package/dist/hosting/managed-resources.d.ts.map +1 -1
  287. package/dist/hosting/managed-resources.js +18 -2
  288. package/dist/hosting/managed-resources.js.map +1 -1
  289. package/dist/hosting/nginx-sites-list.d.ts.map +1 -1
  290. package/dist/hosting/nginx-sites-list.js +39 -3
  291. package/dist/hosting/nginx-sites-list.js.map +1 -1
  292. package/dist/hosting/nginx-ssl.d.ts +4 -0
  293. package/dist/hosting/nginx-ssl.d.ts.map +1 -1
  294. package/dist/hosting/nginx-ssl.js +52 -7
  295. package/dist/hosting/nginx-ssl.js.map +1 -1
  296. package/dist/hosting/nginx-sync.d.ts +34 -0
  297. package/dist/hosting/nginx-sync.d.ts.map +1 -1
  298. package/dist/hosting/nginx-sync.js +258 -11
  299. package/dist/hosting/nginx-sync.js.map +1 -1
  300. package/dist/hosting/ops-log.d.ts +23 -0
  301. package/dist/hosting/ops-log.d.ts.map +1 -0
  302. package/dist/hosting/ops-log.js +15 -0
  303. package/dist/hosting/ops-log.js.map +1 -0
  304. package/dist/hosting/panel-tls.d.ts +9 -0
  305. package/dist/hosting/panel-tls.d.ts.map +1 -1
  306. package/dist/hosting/panel-tls.js +50 -2
  307. package/dist/hosting/panel-tls.js.map +1 -1
  308. package/dist/hosting/pm2-apply.d.ts.map +1 -1
  309. package/dist/hosting/pm2-apply.js +9 -2
  310. package/dist/hosting/pm2-apply.js.map +1 -1
  311. package/dist/hosting/postgres-provision.d.ts.map +1 -1
  312. package/dist/hosting/postgres-provision.js +43 -19
  313. package/dist/hosting/postgres-provision.js.map +1 -1
  314. package/dist/hosting/production-readiness.d.ts.map +1 -1
  315. package/dist/hosting/production-readiness.js +67 -10
  316. package/dist/hosting/production-readiness.js.map +1 -1
  317. package/dist/hosting/project-create-extras.d.ts +37 -0
  318. package/dist/hosting/project-create-extras.d.ts.map +1 -0
  319. package/dist/hosting/project-create-extras.js +47 -0
  320. package/dist/hosting/project-create-extras.js.map +1 -0
  321. package/dist/hosting/project-isolation-status.d.ts.map +1 -1
  322. package/dist/hosting/project-isolation-status.js +10 -2
  323. package/dist/hosting/project-isolation-status.js.map +1 -1
  324. package/dist/hosting/project-ops.d.ts +67 -0
  325. package/dist/hosting/project-ops.d.ts.map +1 -1
  326. package/dist/hosting/project-ops.js +377 -7
  327. package/dist/hosting/project-ops.js.map +1 -1
  328. package/dist/hosting/project-service.d.ts +3 -0
  329. package/dist/hosting/project-service.d.ts.map +1 -1
  330. package/dist/hosting/project-service.js +9 -0
  331. package/dist/hosting/project-service.js.map +1 -1
  332. package/dist/hosting/public-files.d.ts +4 -0
  333. package/dist/hosting/public-files.d.ts.map +1 -1
  334. package/dist/hosting/public-files.js +46 -7
  335. package/dist/hosting/public-files.js.map +1 -1
  336. package/dist/hosting/rebuild.d.ts +1 -0
  337. package/dist/hosting/rebuild.d.ts.map +1 -1
  338. package/dist/hosting/rebuild.js +14 -4
  339. package/dist/hosting/rebuild.js.map +1 -1
  340. package/dist/hosting/runtime-probe.d.ts +7 -0
  341. package/dist/hosting/runtime-probe.d.ts.map +1 -1
  342. package/dist/hosting/runtime-probe.js +74 -7
  343. package/dist/hosting/runtime-probe.js.map +1 -1
  344. package/dist/hosting/runtime.d.ts.map +1 -1
  345. package/dist/hosting/runtime.js +5 -3
  346. package/dist/hosting/runtime.js.map +1 -1
  347. package/dist/hosting/service-catalog/redis.d.ts.map +1 -1
  348. package/dist/hosting/service-catalog/redis.js +2 -1
  349. package/dist/hosting/service-catalog/redis.js.map +1 -1
  350. package/dist/hosting/service-console.d.ts +1 -1
  351. package/dist/hosting/service-console.d.ts.map +1 -1
  352. package/dist/hosting/service-console.js +4 -3
  353. package/dist/hosting/service-console.js.map +1 -1
  354. package/dist/hosting/service-matrix.d.ts +1 -1
  355. package/dist/hosting/service-matrix.d.ts.map +1 -1
  356. package/dist/hosting/service-matrix.js +24 -1
  357. package/dist/hosting/service-matrix.js.map +1 -1
  358. package/dist/hosting/sftp-keys.d.ts.map +1 -1
  359. package/dist/hosting/sftp-keys.js +2 -1
  360. package/dist/hosting/sftp-keys.js.map +1 -1
  361. package/dist/hosting/software-catalog.d.ts +2 -2
  362. package/dist/hosting/software-catalog.d.ts.map +1 -1
  363. package/dist/hosting/software-catalog.js +12 -2
  364. package/dist/hosting/software-catalog.js.map +1 -1
  365. package/dist/hosting/software-install.d.ts +4 -0
  366. package/dist/hosting/software-install.d.ts.map +1 -1
  367. package/dist/hosting/software-install.js +21 -0
  368. package/dist/hosting/software-install.js.map +1 -1
  369. package/dist/hosting/software-probe/HostSoftwareProbe.d.ts.map +1 -1
  370. package/dist/hosting/software-probe/HostSoftwareProbe.js +4 -0
  371. package/dist/hosting/software-probe/HostSoftwareProbe.js.map +1 -1
  372. package/dist/hosting/software-probe/registry.d.ts.map +1 -1
  373. package/dist/hosting/software-probe/registry.js +13 -0
  374. package/dist/hosting/software-probe/registry.js.map +1 -1
  375. package/dist/hosting/software-uninstall.d.ts.map +1 -1
  376. package/dist/hosting/software-uninstall.js +22 -0
  377. package/dist/hosting/software-uninstall.js.map +1 -1
  378. package/dist/hosting/sql-engine-switch/migrate.d.ts.map +1 -1
  379. package/dist/hosting/sql-engine-switch/migrate.js +62 -5
  380. package/dist/hosting/sql-engine-switch/migrate.js.map +1 -1
  381. package/dist/hosting/sql-engine-switch/preview.d.ts +9 -0
  382. package/dist/hosting/sql-engine-switch/preview.d.ts.map +1 -1
  383. package/dist/hosting/sql-engine-switch/preview.js +48 -0
  384. package/dist/hosting/sql-engine-switch/preview.js.map +1 -1
  385. package/dist/hosting/ssl-certs.js +1 -1
  386. package/dist/hosting/ssl-certs.js.map +1 -1
  387. package/dist/hosting/stack/definitions.js +1 -1
  388. package/dist/hosting/stack/definitions.js.map +1 -1
  389. package/dist/hosting/system-apply.d.ts.map +1 -1
  390. package/dist/hosting/system-apply.js +16 -6
  391. package/dist/hosting/system-apply.js.map +1 -1
  392. package/dist/hosting/temp-db-user.d.ts +10 -0
  393. package/dist/hosting/temp-db-user.d.ts.map +1 -1
  394. package/dist/hosting/temp-db-user.js +31 -0
  395. package/dist/hosting/temp-db-user.js.map +1 -1
  396. package/dist/hosting/validators/adapters/ada.d.ts +16 -0
  397. package/dist/hosting/validators/adapters/ada.d.ts.map +1 -0
  398. package/dist/hosting/validators/adapters/ada.js +72 -0
  399. package/dist/hosting/validators/adapters/ada.js.map +1 -0
  400. package/dist/hosting/validators/adapters/avax.d.ts +17 -0
  401. package/dist/hosting/validators/adapters/avax.d.ts.map +1 -0
  402. package/dist/hosting/validators/adapters/avax.js +66 -0
  403. package/dist/hosting/validators/adapters/avax.js.map +1 -0
  404. package/dist/hosting/validators/adapters/base.d.ts +61 -0
  405. package/dist/hosting/validators/adapters/base.d.ts.map +1 -0
  406. package/dist/hosting/validators/adapters/base.js +4 -0
  407. package/dist/hosting/validators/adapters/base.js.map +1 -0
  408. package/dist/hosting/validators/adapters/eth-clients.d.ts +16 -0
  409. package/dist/hosting/validators/adapters/eth-clients.d.ts.map +1 -0
  410. package/dist/hosting/validators/adapters/eth-clients.js +247 -0
  411. package/dist/hosting/validators/adapters/eth-clients.js.map +1 -0
  412. package/dist/hosting/validators/adapters/eth.d.ts +18 -0
  413. package/dist/hosting/validators/adapters/eth.d.ts.map +1 -0
  414. package/dist/hosting/validators/adapters/eth.js +102 -0
  415. package/dist/hosting/validators/adapters/eth.js.map +1 -0
  416. package/dist/hosting/validators/adapters/index.d.ts +5 -0
  417. package/dist/hosting/validators/adapters/index.d.ts.map +1 -0
  418. package/dist/hosting/validators/adapters/index.js +39 -0
  419. package/dist/hosting/validators/adapters/index.js.map +1 -0
  420. package/dist/hosting/validators/adapters/near.d.ts +15 -0
  421. package/dist/hosting/validators/adapters/near.d.ts.map +1 -0
  422. package/dist/hosting/validators/adapters/near.js +72 -0
  423. package/dist/hosting/validators/adapters/near.js.map +1 -0
  424. package/dist/hosting/validators/adapters/phase2.d.ts +33 -0
  425. package/dist/hosting/validators/adapters/phase2.d.ts.map +1 -0
  426. package/dist/hosting/validators/adapters/phase2.js +294 -0
  427. package/dist/hosting/validators/adapters/phase2.js.map +1 -0
  428. package/dist/hosting/validators/compose-runner.d.ts +88 -0
  429. package/dist/hosting/validators/compose-runner.d.ts.map +1 -0
  430. package/dist/hosting/validators/compose-runner.js +178 -0
  431. package/dist/hosting/validators/compose-runner.js.map +1 -0
  432. package/dist/hosting/validators/disk.d.ts +29 -0
  433. package/dist/hosting/validators/disk.d.ts.map +1 -0
  434. package/dist/hosting/validators/disk.js +208 -0
  435. package/dist/hosting/validators/disk.js.map +1 -0
  436. package/dist/hosting/validators/extras.d.ts +82 -0
  437. package/dist/hosting/validators/extras.d.ts.map +1 -0
  438. package/dist/hosting/validators/extras.js +391 -0
  439. package/dist/hosting/validators/extras.js.map +1 -0
  440. package/dist/hosting/validators/health.d.ts +21 -0
  441. package/dist/hosting/validators/health.d.ts.map +1 -0
  442. package/dist/hosting/validators/health.js +65 -0
  443. package/dist/hosting/validators/health.js.map +1 -0
  444. package/dist/hosting/validators/honesty.d.ts +33 -0
  445. package/dist/hosting/validators/honesty.d.ts.map +1 -0
  446. package/dist/hosting/validators/honesty.js +54 -0
  447. package/dist/hosting/validators/honesty.js.map +1 -0
  448. package/dist/hosting/validators/index.d.ts +26 -0
  449. package/dist/hosting/validators/index.d.ts.map +1 -0
  450. package/dist/hosting/validators/index.js +26 -0
  451. package/dist/hosting/validators/index.js.map +1 -0
  452. package/dist/hosting/validators/manager.d.ts +78 -0
  453. package/dist/hosting/validators/manager.d.ts.map +1 -0
  454. package/dist/hosting/validators/manager.js +455 -0
  455. package/dist/hosting/validators/manager.js.map +1 -0
  456. package/dist/hosting/validators/mithril.d.ts +30 -0
  457. package/dist/hosting/validators/mithril.d.ts.map +1 -0
  458. package/dist/hosting/validators/mithril.js +146 -0
  459. package/dist/hosting/validators/mithril.js.map +1 -0
  460. package/dist/hosting/validators/native-prune.d.ts +12 -0
  461. package/dist/hosting/validators/native-prune.d.ts.map +1 -0
  462. package/dist/hosting/validators/native-prune.js +40 -0
  463. package/dist/hosting/validators/native-prune.js.map +1 -0
  464. package/dist/hosting/validators/ports.d.ts +7 -0
  465. package/dist/hosting/validators/ports.d.ts.map +1 -0
  466. package/dist/hosting/validators/ports.js +75 -0
  467. package/dist/hosting/validators/ports.js.map +1 -0
  468. package/dist/hosting/validators/registry.d.ts +22 -0
  469. package/dist/hosting/validators/registry.d.ts.map +1 -0
  470. package/dist/hosting/validators/registry.js +311 -0
  471. package/dist/hosting/validators/registry.js.map +1 -0
  472. package/dist/hosting/validators/releases.d.ts +30 -0
  473. package/dist/hosting/validators/releases.d.ts.map +1 -0
  474. package/dist/hosting/validators/releases.js +149 -0
  475. package/dist/hosting/validators/releases.js.map +1 -0
  476. package/dist/hosting/validators/runtime-status.d.ts +13 -0
  477. package/dist/hosting/validators/runtime-status.d.ts.map +1 -0
  478. package/dist/hosting/validators/runtime-status.js +19 -0
  479. package/dist/hosting/validators/runtime-status.js.map +1 -0
  480. package/dist/hosting/validators/settings.d.ts +4 -0
  481. package/dist/hosting/validators/settings.d.ts.map +1 -0
  482. package/dist/hosting/validators/settings.js +28 -0
  483. package/dist/hosting/validators/settings.js.map +1 -0
  484. package/dist/hosting/validators/snapshots.d.ts +40 -0
  485. package/dist/hosting/validators/snapshots.d.ts.map +1 -0
  486. package/dist/hosting/validators/snapshots.js +221 -0
  487. package/dist/hosting/validators/snapshots.js.map +1 -0
  488. package/dist/hosting/validators/software-catalog.d.ts +24 -0
  489. package/dist/hosting/validators/software-catalog.d.ts.map +1 -0
  490. package/dist/hosting/validators/software-catalog.js +125 -0
  491. package/dist/hosting/validators/software-catalog.js.map +1 -0
  492. package/dist/hosting/validators/store.d.ts +29 -0
  493. package/dist/hosting/validators/store.d.ts.map +1 -0
  494. package/dist/hosting/validators/store.js +186 -0
  495. package/dist/hosting/validators/store.js.map +1 -0
  496. package/dist/hosting/validators/upgrade.d.ts +35 -0
  497. package/dist/hosting/validators/upgrade.d.ts.map +1 -0
  498. package/dist/hosting/validators/upgrade.js +251 -0
  499. package/dist/hosting/validators/upgrade.js.map +1 -0
  500. package/dist/hosting/validators/versions.d.ts +9 -0
  501. package/dist/hosting/validators/versions.d.ts.map +1 -0
  502. package/dist/hosting/validators/versions.js +20 -0
  503. package/dist/hosting/validators/versions.js.map +1 -0
  504. package/dist/hosting/version-discovery.d.ts.map +1 -1
  505. package/dist/hosting/version-discovery.js +15 -6
  506. package/dist/hosting/version-discovery.js.map +1 -1
  507. package/dist/hosting/vnc/client-profiles.d.ts.map +1 -1
  508. package/dist/hosting/vnc/client-profiles.js +12 -6
  509. package/dist/hosting/vnc/client-profiles.js.map +1 -1
  510. package/dist/hosting/vnc/hostname-hosts.d.ts +28 -0
  511. package/dist/hosting/vnc/hostname-hosts.d.ts.map +1 -0
  512. package/dist/hosting/vnc/hostname-hosts.js +177 -0
  513. package/dist/hosting/vnc/hostname-hosts.js.map +1 -0
  514. package/dist/hosting/vnc/index.d.ts +1 -0
  515. package/dist/hosting/vnc/index.d.ts.map +1 -1
  516. package/dist/hosting/vnc/index.js +1 -0
  517. package/dist/hosting/vnc/index.js.map +1 -1
  518. package/dist/hosting/vnc/passwd.d.ts.map +1 -1
  519. package/dist/hosting/vnc/passwd.js +14 -3
  520. package/dist/hosting/vnc/passwd.js.map +1 -1
  521. package/dist/hosting/vnc/server-session.d.ts.map +1 -1
  522. package/dist/hosting/vnc/server-session.js +5 -0
  523. package/dist/hosting/vnc/server-session.js.map +1 -1
  524. package/dist/hosting/vnc/service.d.ts +1 -0
  525. package/dist/hosting/vnc/service.d.ts.map +1 -1
  526. package/dist/hosting/vnc/service.js +80 -9
  527. package/dist/hosting/vnc/service.js.map +1 -1
  528. package/dist/hosting/vnc/types.d.ts +8 -0
  529. package/dist/hosting/vnc/types.d.ts.map +1 -1
  530. package/dist/hosting/vnc/types.js +22 -0
  531. package/dist/hosting/vnc/types.js.map +1 -1
  532. package/dist/hosting/vpn/client-conf-protect.d.ts +5 -0
  533. package/dist/hosting/vpn/client-conf-protect.d.ts.map +1 -1
  534. package/dist/hosting/vpn/client-conf-protect.js +15 -0
  535. package/dist/hosting/vpn/client-conf-protect.js.map +1 -1
  536. package/dist/hosting/vpn/openvpn-ops.d.ts.map +1 -1
  537. package/dist/hosting/vpn/openvpn-ops.js +13 -3
  538. package/dist/hosting/vpn/openvpn-ops.js.map +1 -1
  539. package/dist/hosting/vpn/outline-ops.d.ts.map +1 -1
  540. package/dist/hosting/vpn/outline-ops.js +7 -3
  541. package/dist/hosting/vpn/outline-ops.js.map +1 -1
  542. package/dist/hosting/vpn/ports.d.ts +3 -0
  543. package/dist/hosting/vpn/ports.d.ts.map +1 -1
  544. package/dist/hosting/vpn/ports.js +8 -0
  545. package/dist/hosting/vpn/ports.js.map +1 -1
  546. package/dist/hosting/vpn/service.d.ts +11 -0
  547. package/dist/hosting/vpn/service.d.ts.map +1 -1
  548. package/dist/hosting/vpn/service.js +102 -27
  549. package/dist/hosting/vpn/service.js.map +1 -1
  550. package/dist/hosting/web-stats.d.ts.map +1 -1
  551. package/dist/hosting/web-stats.js +0 -1
  552. package/dist/hosting/web-stats.js.map +1 -1
  553. package/dist/hosting/wizard.d.ts.map +1 -1
  554. package/dist/hosting/wizard.js +53 -63
  555. package/dist/hosting/wizard.js.map +1 -1
  556. package/dist/llm/http-transport.d.ts.map +1 -1
  557. package/dist/llm/http-transport.js +11 -3
  558. package/dist/llm/http-transport.js.map +1 -1
  559. package/dist/monitoring/notifications.d.ts.map +1 -1
  560. package/dist/monitoring/notifications.js +86 -0
  561. package/dist/monitoring/notifications.js.map +1 -1
  562. package/dist/monitoring/process-snapshot.d.ts +2 -0
  563. package/dist/monitoring/process-snapshot.d.ts.map +1 -1
  564. package/dist/monitoring/process-snapshot.js +14 -2
  565. package/dist/monitoring/process-snapshot.js.map +1 -1
  566. package/dist/net/ssrf.d.ts +6 -0
  567. package/dist/net/ssrf.d.ts.map +1 -1
  568. package/dist/net/ssrf.js +80 -15
  569. package/dist/net/ssrf.js.map +1 -1
  570. package/dist/repositories/project-repo.d.ts +1 -1
  571. package/dist/repositories/project-repo.d.ts.map +1 -1
  572. package/dist/repositories/project-repo.js +12 -0
  573. package/dist/repositories/project-repo.js.map +1 -1
  574. package/dist/repositories/settings-repo.d.ts.map +1 -1
  575. package/dist/repositories/settings-repo.js +6 -1
  576. package/dist/repositories/settings-repo.js.map +1 -1
  577. package/dist/security/mfa/rate-limit.d.ts +11 -0
  578. package/dist/security/mfa/rate-limit.d.ts.map +1 -1
  579. package/dist/security/mfa/rate-limit.js +18 -0
  580. package/dist/security/mfa/rate-limit.js.map +1 -1
  581. package/dist/security/mfa/webauthn.d.ts +5 -0
  582. package/dist/security/mfa/webauthn.d.ts.map +1 -1
  583. package/dist/security/mfa/webauthn.js +13 -4
  584. package/dist/security/mfa/webauthn.js.map +1 -1
  585. package/dist/security/ssh-identity/install.d.ts.map +1 -1
  586. package/dist/security/ssh-identity/install.js +12 -0
  587. package/dist/security/ssh-identity/install.js.map +1 -1
  588. package/dist/security/ssh-identity/ops.d.ts +16 -0
  589. package/dist/security/ssh-identity/ops.d.ts.map +1 -1
  590. package/dist/security/ssh-identity/ops.js +73 -3
  591. package/dist/security/ssh-identity/ops.js.map +1 -1
  592. package/dist/services/auth.d.ts +9 -0
  593. package/dist/services/auth.d.ts.map +1 -1
  594. package/dist/services/auth.js +27 -9
  595. package/dist/services/auth.js.map +1 -1
  596. package/dist/services/protection-probe.d.ts.map +1 -1
  597. package/dist/services/protection-probe.js +7 -5
  598. package/dist/services/protection-probe.js.map +1 -1
  599. package/dist/services/scheduler.d.ts +5 -0
  600. package/dist/services/scheduler.d.ts.map +1 -1
  601. package/dist/services/scheduler.js +11 -0
  602. package/dist/services/scheduler.js.map +1 -1
  603. package/dist/services/users-admin.d.ts +1 -0
  604. package/dist/services/users-admin.d.ts.map +1 -1
  605. package/dist/services/users-admin.js +42 -4
  606. package/dist/services/users-admin.js.map +1 -1
  607. package/dist/update/index.d.ts +2 -0
  608. package/dist/update/index.d.ts.map +1 -1
  609. package/dist/update/index.js +2 -0
  610. package/dist/update/index.js.map +1 -1
  611. package/dist/update/inventory.d.ts +2 -0
  612. package/dist/update/inventory.d.ts.map +1 -1
  613. package/dist/update/inventory.js +13 -5
  614. package/dist/update/inventory.js.map +1 -1
  615. package/dist/update/self-update-apply.d.ts +55 -0
  616. package/dist/update/self-update-apply.d.ts.map +1 -1
  617. package/dist/update/self-update-apply.js +238 -66
  618. package/dist/update/self-update-apply.js.map +1 -1
  619. package/dist/update/self-update-overlay.d.ts +54 -0
  620. package/dist/update/self-update-overlay.d.ts.map +1 -0
  621. package/dist/update/self-update-overlay.js +360 -0
  622. package/dist/update/self-update-overlay.js.map +1 -0
  623. package/dist/update/update-hub.d.ts +45 -0
  624. package/dist/update/update-hub.d.ts.map +1 -0
  625. package/dist/update/update-hub.js +217 -0
  626. package/dist/update/update-hub.js.map +1 -0
  627. package/package.json +10 -13
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Real backup (tar) and cron job management under dataDir.
3
3
  */
4
- import { existsSync, mkdirSync, readdirSync, writeFileSync, readFileSync, statSync, unlinkSync } from 'node:fs';
4
+ import { existsSync, mkdirSync, readdirSync, writeFileSync, readFileSync, renameSync, copyFileSync, statSync, unlinkSync } from 'node:fs';
5
5
  import { join, resolve, sep } from 'node:path';
6
6
  import { randomUUID } from 'node:crypto';
7
7
  import { ErrorCodes, YskError, tl } from 'ysk-server-shared';
8
8
  import { planCronJob } from './extras.js';
9
+ import { publicFilesRoot } from '../files/manager.js';
9
10
  /** Constrain archive under dataDir/backups/<projectId>/ */
10
11
  export function resolveManagedBackupArchive(dataDir, projectId, archiveName) {
11
12
  const id = String(projectId ?? '')
@@ -36,6 +37,8 @@ export function listBackups(dataDir) {
36
37
  return [];
37
38
  const out = [];
38
39
  for (const projectId of readdirSync(root)) {
40
+ if (projectId === '.trash' || projectId.startsWith('.'))
41
+ continue;
39
42
  const dir = join(root, projectId);
40
43
  try {
41
44
  if (!statSync(dir).isDirectory())
@@ -61,10 +64,16 @@ export function listBackups(dataDir) {
61
64
  /** Notes that mean "not attempted" (skip) — Chinese or English */
62
65
  export function isBackupSkipNote(note) {
63
66
  const n = note.trim();
64
- return (/^skip\b/i.test(n) ||
65
- /^skipped\b/i.test(n) ||
66
- n.startsWith(tl('notes.auto.n1252')) ||
67
- n.startsWith(tl('notes.auto.n1461')));
67
+ if (!n)
68
+ return false;
69
+ if (/blocked|YSK_EXECUTE|YSK_FORBIDDEN|requires execute/i.test(n))
70
+ return false;
71
+ if (/^skip(?:ped)?\b/i.test(n))
72
+ return true;
73
+ const prefixes = [tl('notes.auto.n1252'), tl('notes.auto.n1461')]
74
+ .map((p) => p.trim())
75
+ .filter((p) => p.length >= 2);
76
+ return prefixes.some((p) => n.startsWith(p));
68
77
  }
69
78
  export function isBackupSkippedResult(r) {
70
79
  if (r.skipped === true)
@@ -149,16 +158,31 @@ export function localizeLastBackupRun(last) {
149
158
  const results = Array.isArray(last.results)
150
159
  ? last.results
151
160
  : [];
152
- const asSkip = (r) => isBackupSkippedResult({ ok: r.ok, notes: r.notes ?? [], skipped: r.skipped });
153
- const skipped = results.filter(asSkip);
154
- const attempted = results.filter((r) => !asSkip(r));
161
+ const asSkip = (r) => r.skipped === true ||
162
+ isBackupSkippedResult({ ok: r.ok, notes: r.notes ?? [], skipped: r.skipped });
163
+ let skipped = results.filter(asSkip);
164
+ let attempted = results.filter((r) => !asSkip(r));
165
+ const singleProjectOk = String(last.source || '') === 'projects.backup' && Boolean(last.archivePath);
166
+ if (singleProjectOk && attempted.length === 0) {
167
+ attempted = [{ ok: true, notes: [] }];
168
+ skipped = [];
169
+ }
155
170
  const okCount = attempted.filter((r) => r.ok).length;
156
171
  const notes = [
157
172
  tl('notes.auto.t0326', { v0: okCount, v1: attempted.length }) +
158
173
  (skipped.length ? tl('notes.auto.t0327', { v0: skipped.length }) : ''),
159
174
  ];
160
- if (last.ok === true) {
161
- notes.push(attempted.length === 0 ? tl('notes.auto.n0590') : tl('notes.auto.n0589'));
175
+ const singleOk = last.ok === true || singleProjectOk;
176
+ if (singleOk) {
177
+ notes.push(attempted.length === 0 && String(last.source || '') !== 'projects.backup'
178
+ ? tl('notes.auto.n0590')
179
+ : tl('notes.auto.n0589'));
180
+ }
181
+ else if (last.ok === false) {
182
+ notes.push(tl('notes.auto.n1492'));
183
+ }
184
+ else if (attempted.length === 0 && results.length === 0 && last.archivePath) {
185
+ notes.push(tl('notes.auto.n0589'));
162
186
  }
163
187
  else {
164
188
  notes.push(tl('notes.auto.n1492'));
@@ -188,7 +212,19 @@ export async function backupProject(input) {
188
212
  const stamp = new Date().toISOString().replace(/[:.]/g, '-');
189
213
  const archivePath = join(destDir, `backup-${stamp}.tar.gz`);
190
214
  const sources = [input.homeDir, ...(input.extraSources ?? [])];
191
- const excludeArgs = (input.excludes ?? []).flatMap((e) => ['--exclude', e]);
215
+ const defaultExcludes = [
216
+ '.env',
217
+ '.env.*',
218
+ '.db.env',
219
+ 'app/.env',
220
+ 'app/.db.env',
221
+ '**/.env',
222
+ '**/.db.env',
223
+ ];
224
+ const excludeArgs = [...defaultExcludes, ...(input.excludes ?? [])].flatMap((e) => [
225
+ '--exclude',
226
+ e,
227
+ ]);
192
228
  // tar from parent with relative paths when possible
193
229
  const tarTimeoutMs = 600_000; // large homes
194
230
  const r = await input.host.runCommand([
@@ -236,14 +272,92 @@ export async function backupProject(input) {
236
272
  /* ignore */
237
273
  }
238
274
  }
275
+ const notes = [
276
+ tl('notes.auto.t0330', { v0: archivePath }),
277
+ tl('notes.auto.n0556'),
278
+ ];
279
+ let includesDatabase = false;
280
+ const sidecar = await maybeDumpSqlSidecar({
281
+ host: input.host,
282
+ dataDir: input.dataDir,
283
+ homeDir: input.homeDir,
284
+ destDir,
285
+ stamp,
286
+ });
287
+ notes.push(...sidecar.notes);
288
+ includesDatabase = sidecar.ok;
289
+ if (!includesDatabase) {
290
+ notes.push('Home tar only — no SQL dump. .env / .db.env excluded.');
291
+ }
239
292
  return {
240
293
  ok: true,
241
294
  archivePath,
242
295
  bytes,
243
- notes: [tl('notes.auto.t0330', { v0: (archivePath) }), tl('notes.auto.n0556')],
296
+ includesDatabase,
297
+ notes,
244
298
  commandResults: [{ argv: ['tar', '-czf', archivePath], exitCode: 0, stderr: '' }]
245
299
  };
246
300
  }
301
+ export function parseDbEnvFile(text) {
302
+ const map = {};
303
+ for (const line of text.split('\n')) {
304
+ const raw = line.trim();
305
+ if (!raw || raw.startsWith('#'))
306
+ continue;
307
+ const i = raw.indexOf('=');
308
+ if (i < 0)
309
+ continue;
310
+ const k = raw.slice(0, i).trim().toUpperCase();
311
+ const v = raw.slice(i + 1).trim().replace(/^['"]|['"]$/g, '');
312
+ map[k] = v;
313
+ }
314
+ const engineRaw = (map.ENGINE || map.DB_ENGINE || map.DB_DRIVER || '').toLowerCase();
315
+ let engine = 'mariadb';
316
+ if (engineRaw.includes('postgres') || engineRaw.includes('pgsql'))
317
+ engine = 'postgres';
318
+ else if (engineRaw.includes('mysql') && !engineRaw.includes('maria'))
319
+ engine = 'mysql';
320
+ return {
321
+ engine,
322
+ dbName: map.DB || map.DB_NAME || map.MYSQL_DATABASE || map.POSTGRES_DB,
323
+ username: map.USER || map.DB_USER || map.MYSQL_USER || map.POSTGRES_USER,
324
+ password: map.PASSWORD || map.DB_PASSWORD || map.MYSQL_PASSWORD || map.POSTGRES_PASSWORD,
325
+ };
326
+ }
327
+ async function maybeDumpSqlSidecar(input) {
328
+ const candidates = [join(input.homeDir, '.db.env'), join(input.homeDir, 'app', '.db.env')];
329
+ let envPath = '';
330
+ for (const p of candidates) {
331
+ if (existsSync(p)) {
332
+ envPath = p;
333
+ break;
334
+ }
335
+ }
336
+ if (!envPath)
337
+ return { ok: false, notes: [] };
338
+ let parsed;
339
+ try {
340
+ parsed = parseDbEnvFile(readFileSync(envPath, 'utf8'));
341
+ }
342
+ catch {
343
+ return { ok: false, notes: [tl('notes.backup.dbEnvUnreadable')] };
344
+ }
345
+ if (!parsed.dbName) {
346
+ return { ok: false, notes: [tl('notes.backup.dbEnvNoName')] };
347
+ }
348
+ const { dumpSqlDatabase } = await import('./db-dump.js');
349
+ const out = join(input.destDir, `backup-${input.stamp}.sql`);
350
+ const dump = await dumpSqlDatabase({
351
+ host: input.host,
352
+ dataDir: input.dataDir,
353
+ engine: parsed.engine,
354
+ dbName: parsed.dbName,
355
+ username: parsed.username,
356
+ password: parsed.password,
357
+ outputPath: out,
358
+ });
359
+ return { ok: Boolean(dump.ok), notes: dump.notes };
360
+ }
247
361
  /**
248
362
  * Restore a managed backup archive into the project home.
249
363
  * Path must live under dataDir/backups/<projectId>/ — never accepts arbitrary paths.
@@ -262,15 +376,16 @@ export async function restoreProjectBackup(input) {
262
376
  const mode = input.mode ?? 'full';
263
377
  if (mode === 'dry-run') {
264
378
  const r = await input.host.runCommand(['tar', '-tzf', archivePath], { timeoutMs: 60_000 });
265
- const listing = (r.stdout || '').split('\n').filter(Boolean).slice(0, 80);
379
+ const listing = (r.stdout || '').split('\n').filter(Boolean);
380
+ const shown = listing.slice(0, 12);
266
381
  return {
267
382
  ok: r.exitCode === 0,
268
383
  archivePath,
269
384
  notes: [
270
385
  r.exitCode === 0
271
- ? tl('notes.auto.t0331', { v0: (listing.length), v1: (listing.length) })
386
+ ? tl('notes.auto.t0331', { v0: listing.length, v1: shown.length })
272
387
  : tl('notes.auto.t0332', { v0: (r.stderr) }),
273
- ...listing.slice(0, 12).map((l) => ` ${l}`),
388
+ ...shown.map((l) => ` ${l}`),
274
389
  ],
275
390
  commandResults: [{ argv: ['tar', '-tzf', archivePath], exitCode: r.exitCode, stderr: r.stderr }]
276
391
  };
@@ -278,21 +393,23 @@ export async function restoreProjectBackup(input) {
278
393
  if (!existsSync(input.homeDir)) {
279
394
  mkdirSync(input.homeDir, { recursive: true });
280
395
  }
281
- if (mode === 'web') {
282
- // Extract only into project home (safer partial restore for web files)
283
- const r2 = await input.host.runCommand(['tar', '-xzf', archivePath, '-C', input.homeDir], { timeoutMs: 180_000 });
396
+ const destHome = resolveRestoreTargetDir(input.homeDir, input.dataDir, input.targetDir);
397
+ if (!existsSync(destHome))
398
+ mkdirSync(destHome, { recursive: true });
399
+ if (mode === 'web' || input.targetDir) {
400
+ const r2 = await input.host.runCommand(['tar', '-xzf', archivePath, '-C', destHome], { timeoutMs: 180_000 });
284
401
  const notes = r2.exitCode === 0
285
- ? [tl('notes.auto.t0333', { v0: (input.homeDir) })]
402
+ ? [tl('notes.auto.t0333', { v0: destHome })]
286
403
  : [tl('notes.auto.t0334', { v0: (r2.stderr) })];
287
404
  if (r2.exitCode === 0) {
288
- notes.push(...(await chownAfterRestore(input)));
405
+ notes.push(...(await chownAfterRestore({ ...input, homeDir: destHome })));
289
406
  }
290
407
  return {
291
408
  ok: r2.exitCode === 0,
292
409
  archivePath,
293
410
  notes,
294
411
  commandResults: [
295
- { argv: ['tar', '-xzf', archivePath, '-C', input.homeDir], exitCode: r2.exitCode, stderr: r2.stderr },
412
+ { argv: ['tar', '-xzf', archivePath, '-C', destHome], exitCode: r2.exitCode, stderr: r2.stderr },
296
413
  ]
297
414
  };
298
415
  }
@@ -301,7 +418,7 @@ export async function restoreProjectBackup(input) {
301
418
  timeoutMs: 180_000
302
419
  });
303
420
  if (r.exitCode !== 0) {
304
- const r2 = await input.host.runCommand(['tar', '-xzf', archivePath, '-C', input.homeDir], { timeoutMs: 180_000 });
421
+ const r2 = await input.host.runCommand(['tar', '-xzf', archivePath, '-C', destHome], { timeoutMs: 180_000 });
305
422
  if (r2.exitCode !== 0) {
306
423
  return {
307
424
  ok: false,
@@ -321,6 +438,22 @@ export async function restoreProjectBackup(input) {
321
438
  commandResults: [{ argv: ['tar', '-xzf', archivePath], exitCode: 0, stderr: '' }]
322
439
  };
323
440
  }
441
+ function resolveRestoreTargetDir(homeDir, dataDir, targetDir) {
442
+ if (!targetDir?.trim())
443
+ return homeDir;
444
+ const abs = resolve(targetDir.trim());
445
+ const allow = [resolve(homeDir), resolve(publicFilesRoot(dataDir))];
446
+ const ok = allow.some((root) => {
447
+ const prefix = root.endsWith(sep) ? root : root + sep;
448
+ return abs === root || abs.startsWith(prefix);
449
+ });
450
+ if (!ok) {
451
+ throw new YskError(ErrorCodes.SANDBOX_VIOLATION, tl('notes.backup.targetOutside'), {
452
+ httpStatus: 403,
453
+ });
454
+ }
455
+ return abs;
456
+ }
324
457
  async function chownAfterRestore(input) {
325
458
  const u = input.linuxUser?.trim();
326
459
  if (!u)
@@ -338,8 +471,144 @@ async function chownAfterRestore(input) {
338
471
  ? [tl('notes.auto.t0337', { v0: (u), v1: (g), v2: (input.homeDir) })]
339
472
  : [tl('notes.tpl.chownFailed', { detail: (r.stderr || r.stdout).slice(0, 120) })];
340
473
  }
341
- /** Delete one managed backup archive (path constrained). */
474
+ export const BACKUP_TRASH_DAYS = 7;
475
+ export const BACKUP_TRASH_RETENTION_MS = BACKUP_TRASH_DAYS * 24 * 60 * 60 * 1000;
476
+ const TRASH_DIR = '.trash';
477
+ function trashRoot(dataDir) {
478
+ return resolve(join(dataDir, 'backups', TRASH_DIR));
479
+ }
480
+ function resolveTrashArchive(dataDir, projectId, archiveName) {
481
+ const id = String(projectId ?? '')
482
+ .replace(/[^a-zA-Z0-9_-]/g, '')
483
+ .slice(0, 80);
484
+ if (!id)
485
+ return { ok: false, notes: [tl('notes.auto.n1115')] };
486
+ const safeName = String(archiveName ?? '')
487
+ .replace(/[/\\]/g, '')
488
+ .replace(/\0/g, '');
489
+ if (!safeName.endsWith('.tar.gz') || safeName.includes('..')) {
490
+ return { ok: false, notes: [tl('notes.auto.n1116')] };
491
+ }
492
+ const root = resolve(join(trashRoot(dataDir), id));
493
+ const archivePath = resolve(join(root, safeName));
494
+ const rootPrefix = root.endsWith(sep) ? root : root + sep;
495
+ if (archivePath !== root && !archivePath.startsWith(rootPrefix)) {
496
+ return { ok: false, notes: [tl('notes.auto.n1460')] };
497
+ }
498
+ return { ok: true, root, path: archivePath, name: safeName, metaPath: `${archivePath}.json` };
499
+ }
500
+ function moveFile(src, dest) {
501
+ try {
502
+ renameSync(src, dest);
503
+ }
504
+ catch {
505
+ copyFileSync(src, dest);
506
+ unlinkSync(src);
507
+ }
508
+ }
509
+ function writeTrashMeta(metaPath, meta) {
510
+ writeFileSync(metaPath, JSON.stringify(meta), 'utf8');
511
+ }
512
+ function readTrashMeta(metaPath, fallback) {
513
+ try {
514
+ const parsed = JSON.parse(readFileSync(metaPath, 'utf8'));
515
+ if (parsed.deletedAt && parsed.originalName) {
516
+ return {
517
+ deletedAt: String(parsed.deletedAt),
518
+ originalName: String(parsed.originalName),
519
+ bytes: Number(parsed.bytes) || fallback.bytes,
520
+ projectId: String(parsed.projectId || fallback.projectId),
521
+ };
522
+ }
523
+ }
524
+ catch {
525
+ /* use fallback */
526
+ }
527
+ return fallback;
528
+ }
529
+ export function purgeExpiredBackupTrash(dataDir, nowMs = Date.now()) {
530
+ const root = trashRoot(dataDir);
531
+ if (!existsSync(root))
532
+ return 0;
533
+ let n = 0;
534
+ for (const projectId of readdirSync(root)) {
535
+ const dir = join(root, projectId);
536
+ try {
537
+ if (!statSync(dir).isDirectory())
538
+ continue;
539
+ for (const name of readdirSync(dir).filter((f) => f.endsWith('.tar.gz'))) {
540
+ const path = join(dir, name);
541
+ const metaPath = `${path}.json`;
542
+ const st = statSync(path);
543
+ const meta = readTrashMeta(metaPath, {
544
+ deletedAt: st.mtime.toISOString(),
545
+ originalName: name,
546
+ bytes: st.size,
547
+ projectId,
548
+ });
549
+ const deletedMs = Date.parse(meta.deletedAt);
550
+ if (!Number.isFinite(deletedMs) || nowMs - deletedMs < BACKUP_TRASH_RETENTION_MS)
551
+ continue;
552
+ try {
553
+ unlinkSync(path);
554
+ if (existsSync(metaPath))
555
+ unlinkSync(metaPath);
556
+ n += 1;
557
+ }
558
+ catch {
559
+ /* keep */
560
+ }
561
+ }
562
+ }
563
+ catch {
564
+ /* skip */
565
+ }
566
+ }
567
+ return n;
568
+ }
569
+ export function listBackupTrash(dataDir, nowMs = Date.now()) {
570
+ purgeExpiredBackupTrash(dataDir, nowMs);
571
+ const root = trashRoot(dataDir);
572
+ if (!existsSync(root))
573
+ return [];
574
+ const out = [];
575
+ for (const projectId of readdirSync(root)) {
576
+ const dir = join(root, projectId);
577
+ try {
578
+ if (!statSync(dir).isDirectory())
579
+ continue;
580
+ for (const name of readdirSync(dir).filter((f) => f.endsWith('.tar.gz'))) {
581
+ const path = join(dir, name);
582
+ const st = statSync(path);
583
+ const meta = readTrashMeta(`${path}.json`, {
584
+ deletedAt: st.mtime.toISOString(),
585
+ originalName: name,
586
+ bytes: st.size,
587
+ projectId,
588
+ });
589
+ const deletedMs = Date.parse(meta.deletedAt);
590
+ const expiresAt = new Date((Number.isFinite(deletedMs) ? deletedMs : st.mtimeMs) + BACKUP_TRASH_RETENTION_MS).toISOString();
591
+ out.push({
592
+ projectId,
593
+ name: meta.originalName,
594
+ trashName: name,
595
+ path,
596
+ bytes: st.size,
597
+ mtime: st.mtime.toISOString(),
598
+ deletedAt: meta.deletedAt,
599
+ expiresAt,
600
+ });
601
+ }
602
+ }
603
+ catch {
604
+ /* skip */
605
+ }
606
+ }
607
+ return out.sort((a, b) => (a.deletedAt < b.deletedAt ? 1 : -1));
608
+ }
609
+ /** Move one managed backup into the 7-day trash (path constrained). */
342
610
  export function deleteProjectBackup(dataDir, projectId, archiveName) {
611
+ purgeExpiredBackupTrash(dataDir);
343
612
  const resolved = resolveManagedBackupArchive(dataDir, projectId, archiveName);
344
613
  if (!resolved.ok)
345
614
  return { ok: false, notes: resolved.notes };
@@ -347,13 +616,103 @@ export function deleteProjectBackup(dataDir, projectId, archiveName) {
347
616
  return { ok: false, notes: [tl('notes.backup.fileNotFound')] };
348
617
  }
349
618
  try {
350
- unlinkSync(resolved.path);
351
- return { ok: true, notes: [tl('notes.tpl.deleted', { name: resolved.name })] };
619
+ const st = statSync(resolved.path);
620
+ let trashName = resolved.name;
621
+ let dest = resolveTrashArchive(dataDir, projectId, trashName);
622
+ if (!dest.ok)
623
+ return { ok: false, notes: dest.notes };
624
+ if (existsSync(dest.path)) {
625
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
626
+ trashName = resolved.name.replace(/\.tar\.gz$/i, `-${stamp}.tar.gz`);
627
+ dest = resolveTrashArchive(dataDir, projectId, trashName);
628
+ if (!dest.ok)
629
+ return { ok: false, notes: dest.notes };
630
+ }
631
+ mkdirSync(dest.root, { recursive: true });
632
+ moveFile(resolved.path, dest.path);
633
+ const deletedAt = new Date().toISOString();
634
+ writeTrashMeta(dest.metaPath, {
635
+ deletedAt,
636
+ originalName: resolved.name,
637
+ bytes: st.size,
638
+ projectId,
639
+ });
640
+ const expiresAt = new Date(Date.parse(deletedAt) + BACKUP_TRASH_RETENTION_MS).toISOString();
641
+ return {
642
+ ok: true,
643
+ trashed: true,
644
+ expiresAt,
645
+ notes: [tl('notes.backup.movedToTrash', { name: resolved.name, days: BACKUP_TRASH_DAYS })],
646
+ };
352
647
  }
353
648
  catch (e) {
354
649
  return { ok: false, notes: [e instanceof Error ? e.message : String(e)] };
355
650
  }
356
651
  }
652
+ export function restoreBackupTrash(dataDir, projectId, trashName) {
653
+ const dest = resolveTrashArchive(dataDir, projectId, trashName);
654
+ if (!dest.ok)
655
+ return { ok: false, notes: dest.notes };
656
+ if (!existsSync(dest.path)) {
657
+ return { ok: false, notes: [tl('notes.backup.fileNotFound')] };
658
+ }
659
+ const meta = readTrashMeta(dest.metaPath, {
660
+ deletedAt: new Date().toISOString(),
661
+ originalName: dest.name,
662
+ bytes: 0,
663
+ projectId,
664
+ });
665
+ const live = resolveManagedBackupArchive(dataDir, projectId, meta.originalName);
666
+ if (!live.ok)
667
+ return { ok: false, notes: live.notes };
668
+ if (existsSync(live.path)) {
669
+ return { ok: false, notes: [tl('notes.backup.restoreNameExists', { name: meta.originalName })] };
670
+ }
671
+ try {
672
+ mkdirSync(live.root, { recursive: true });
673
+ moveFile(dest.path, live.path);
674
+ if (existsSync(dest.metaPath))
675
+ unlinkSync(dest.metaPath);
676
+ return { ok: true, notes: [tl('notes.backup.restoredFromTrash', { name: meta.originalName })] };
677
+ }
678
+ catch (e) {
679
+ return { ok: false, notes: [e instanceof Error ? e.message : String(e)] };
680
+ }
681
+ }
682
+ export function purgeBackupTrash(dataDir, projectId, trashName) {
683
+ const dest = resolveTrashArchive(dataDir, projectId, trashName);
684
+ if (!dest.ok)
685
+ return { ok: false, notes: dest.notes };
686
+ if (!existsSync(dest.path)) {
687
+ return { ok: false, notes: [tl('notes.backup.fileNotFound')] };
688
+ }
689
+ try {
690
+ unlinkSync(dest.path);
691
+ if (existsSync(dest.metaPath))
692
+ unlinkSync(dest.metaPath);
693
+ return { ok: true, notes: [tl('notes.tpl.deleted', { name: dest.name })] };
694
+ }
695
+ catch (e) {
696
+ return { ok: false, notes: [e instanceof Error ? e.message : String(e)] };
697
+ }
698
+ }
699
+ export function emptyBackupTrash(dataDir) {
700
+ const items = listBackupTrash(dataDir);
701
+ let purged = 0;
702
+ const notes = [];
703
+ for (const item of items) {
704
+ const r = purgeBackupTrash(dataDir, item.projectId, item.trashName);
705
+ if (r.ok)
706
+ purged += 1;
707
+ else
708
+ notes.push(...r.notes);
709
+ }
710
+ return {
711
+ ok: notes.length === 0,
712
+ purged,
713
+ notes: notes.length ? notes : [tl('notes.backup.trashEmptied', { n: purged })],
714
+ };
715
+ }
357
716
  /** Resolve a managed backup path for download (path constrained). */
358
717
  export function resolveBackupDownloadPath(dataDir, projectId, archiveName) {
359
718
  const resolved = resolveManagedBackupArchive(dataDir, projectId, archiveName);
@@ -474,16 +833,17 @@ export async function restoreControlPlaneBackup(input) {
474
833
  }
475
834
  if (mode === 'dry-run') {
476
835
  const r = await input.host.runCommand(['tar', '-tzf', archivePath], { timeoutMs: 60_000 });
477
- const listing = (r.stdout || '').split('\n').filter(Boolean).slice(0, 40);
836
+ const listing = (r.stdout || '').split('\n').filter(Boolean);
837
+ const shown = listing.slice(0, 12);
478
838
  return {
479
839
  ok: r.exitCode === 0,
480
840
  archivePath,
481
841
  notes: [
482
842
  r.exitCode === 0
483
- ? tl('notes.auto.t0331', { v0: listing.length, v1: listing.length })
843
+ ? tl('notes.auto.t0331', { v0: listing.length, v1: shown.length })
484
844
  : tl('notes.auto.t0332', { v0: r.stderr }),
485
- 'dry-run only — pass mode=full + confirmPhrase=RESTORE-CONTROL-PLANE to write',
486
- ...listing.slice(0, 12).map((l) => ` ${l}`),
845
+ tl('notes.backup.controlPlaneDryRun'),
846
+ ...shown.map((l) => ` ${l}`),
487
847
  ],
488
848
  commandResults: [{ argv: ['tar', '-tzf', archivePath], exitCode: r.exitCode, stderr: r.stderr }],
489
849
  };
@@ -493,8 +853,8 @@ export async function restoreControlPlaneBackup(input) {
493
853
  ok: false,
494
854
  archivePath,
495
855
  notes: [
496
- 'refused: full control-plane restore requires confirmPhrase=RESTORE-CONTROL-PLANE',
497
- 'restart API after a successful restore',
856
+ tl('notes.backup.controlPlaneNeedConfirm'),
857
+ tl('notes.backup.controlPlaneRestartAfter'),
498
858
  ],
499
859
  commandResults: [],
500
860
  };
@@ -694,6 +1054,30 @@ export class CronJobService {
694
1054
  this.writeManagedCrontab();
695
1055
  return { ...row };
696
1056
  }
1057
+ update(id, patch) {
1058
+ const row = cronRows(this.db).find((j) => j.id === id);
1059
+ if (!row)
1060
+ return undefined;
1061
+ if (typeof patch.schedule === 'string' && patch.schedule.trim()) {
1062
+ row.schedule = patch.schedule.trim();
1063
+ }
1064
+ if (typeof patch.command === 'string' && patch.command.trim()) {
1065
+ row.command = patch.command.trim();
1066
+ }
1067
+ if (typeof patch.user === 'string' && patch.user.trim()) {
1068
+ row.user = patch.user.trim();
1069
+ }
1070
+ if (patch.projectId !== undefined) {
1071
+ row.project_id = patch.projectId || undefined;
1072
+ }
1073
+ if (typeof patch.enabled === 'boolean') {
1074
+ row.enabled = patch.enabled;
1075
+ }
1076
+ row.updated_at = new Date().toISOString();
1077
+ this.db.persist();
1078
+ this.writeManagedCrontab();
1079
+ return { ...row };
1080
+ }
697
1081
  /**
698
1082
  * Run job command once (test). Requires EXECUTE; fail-closed.
699
1083
  */
@@ -808,6 +1192,8 @@ export class CronJobService {
808
1192
  return false;
809
1193
  if (t.startsWith('# Generated by YSK Server'))
810
1194
  return false;
1195
+ if (t.startsWith('# YSK Server crontab merge'))
1196
+ return false;
811
1197
  if (/#\s*ysk:/i.test(t))
812
1198
  return false;
813
1199
  if (/\bysk-server\b/.test(t) && /backup|cron/i.test(t))
@@ -848,8 +1234,10 @@ export class CronJobService {
848
1234
  if (ok) {
849
1235
  notes.push(tl('notes.cron.installReplacesYskOnly'));
850
1236
  }
1237
+ const at = new Date().toISOString();
1238
+ this.db.snapshot.settings.last_cron_install = JSON.stringify({ ok, at, actor });
851
1239
  for (const j of this.db.snapshot.cron_jobs) {
852
- j.last_install = { ok, at: new Date().toISOString(), actor };
1240
+ j.last_install = { ok, at, actor };
853
1241
  }
854
1242
  this.db.persist();
855
1243
  return {
@@ -866,14 +1254,9 @@ export class CronJobService {
866
1254
  * Non-root: only `crontab -l` for the control-plane process user (honest partial).
867
1255
  */
868
1256
  async listHostCrontabs(projects = []) {
869
- const executeEnabled = this.host.executeEnabled();
870
1257
  const isRoot = this.host.isRoot();
871
1258
  const notes = [];
872
1259
  let partial = false;
873
- if (!executeEnabled) {
874
- notes.push(tl('notes.auto.n1165'));
875
- partial = true;
876
- }
877
1260
  const users = [];
878
1261
  const lines = [];
879
1262
  let slots;
@@ -950,7 +1333,7 @@ export class CronJobService {
950
1333
  notes,
951
1334
  partial,
952
1335
  isRoot,
953
- executeEnabled,
1336
+ executeEnabled: this.host.executeEnabled(),
954
1337
  };
955
1338
  }
956
1339
  /** Probe managed file vs host crontab (honest status). */
@@ -999,7 +1382,17 @@ export class CronJobService {
999
1382
  catch {
1000
1383
  hostHasYskEntries = null;
1001
1384
  }
1002
- const last = all.map((j) => j.last_install).find((x) => x && typeof x === 'object');
1385
+ let last = all.map((j) => j.last_install).find((x) => x && typeof x === 'object');
1386
+ if (!last) {
1387
+ try {
1388
+ const raw = this.db.snapshot.settings?.last_cron_install;
1389
+ if (raw)
1390
+ last = JSON.parse(raw);
1391
+ }
1392
+ catch {
1393
+ /* ignore */
1394
+ }
1395
+ }
1003
1396
  return {
1004
1397
  managedPath: path,
1005
1398
  managedLines,