@omnitron-dev/omnitron 0.1.3 → 0.3.0

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 (1253) hide show
  1. package/dist/BUILD.json +5 -0
  2. package/dist/cli/omnitron.js +378 -25
  3. package/dist/cli/omnitron.js.map +1 -1
  4. package/dist/cluster/cluster.rpc-service.d.ts +40 -0
  5. package/dist/cluster/cluster.rpc-service.d.ts.map +1 -1
  6. package/dist/cluster/cluster.rpc-service.js +49 -3
  7. package/dist/cluster/cluster.rpc-service.js.map +1 -1
  8. package/dist/cluster/config-sync.d.ts.map +1 -1
  9. package/dist/cluster/config-sync.js.map +1 -1
  10. package/dist/cluster/leader-election.d.ts +90 -2
  11. package/dist/cluster/leader-election.d.ts.map +1 -1
  12. package/dist/cluster/leader-election.js +176 -24
  13. package/dist/cluster/leader-election.js.map +1 -1
  14. package/dist/cluster/mesh-link.d.ts +136 -0
  15. package/dist/cluster/mesh-link.d.ts.map +1 -0
  16. package/dist/cluster/mesh-link.js +212 -0
  17. package/dist/cluster/mesh-link.js.map +1 -0
  18. package/dist/cluster/mesh.d.ts +59 -0
  19. package/dist/cluster/mesh.d.ts.map +1 -0
  20. package/dist/cluster/mesh.js +117 -0
  21. package/dist/cluster/mesh.js.map +1 -0
  22. package/dist/cluster/slave-connector.d.ts +193 -9
  23. package/dist/cluster/slave-connector.d.ts.map +1 -1
  24. package/dist/cluster/slave-connector.js +409 -37
  25. package/dist/cluster/slave-connector.js.map +1 -1
  26. package/dist/commands/audit.d.ts +65 -0
  27. package/dist/commands/audit.d.ts.map +1 -0
  28. package/dist/commands/audit.js +233 -0
  29. package/dist/commands/audit.js.map +1 -0
  30. package/dist/commands/backup.d.ts +4 -0
  31. package/dist/commands/backup.d.ts.map +1 -1
  32. package/dist/commands/backup.js +255 -33
  33. package/dist/commands/backup.js.map +1 -1
  34. package/dist/commands/cluster.d.ts.map +1 -1
  35. package/dist/commands/cluster.js +78 -47
  36. package/dist/commands/cluster.js.map +1 -1
  37. package/dist/commands/daemon-cmd.d.ts +7 -1
  38. package/dist/commands/daemon-cmd.d.ts.map +1 -1
  39. package/dist/commands/daemon-cmd.js +87 -21
  40. package/dist/commands/daemon-cmd.js.map +1 -1
  41. package/dist/commands/daemon-required.d.ts +34 -0
  42. package/dist/commands/daemon-required.d.ts.map +1 -0
  43. package/dist/commands/daemon-required.js +92 -0
  44. package/dist/commands/daemon-required.js.map +1 -0
  45. package/dist/commands/deploy.d.ts +70 -8
  46. package/dist/commands/deploy.d.ts.map +1 -1
  47. package/dist/commands/deploy.js +99 -64
  48. package/dist/commands/deploy.js.map +1 -1
  49. package/dist/commands/discover.d.ts +25 -4
  50. package/dist/commands/discover.d.ts.map +1 -1
  51. package/dist/commands/discover.js +155 -102
  52. package/dist/commands/discover.js.map +1 -1
  53. package/dist/commands/doctor.d.ts +293 -0
  54. package/dist/commands/doctor.d.ts.map +1 -0
  55. package/dist/commands/doctor.js +1706 -0
  56. package/dist/commands/doctor.js.map +1 -0
  57. package/dist/commands/env.d.ts +8 -1
  58. package/dist/commands/env.d.ts.map +1 -1
  59. package/dist/commands/env.js +18 -5
  60. package/dist/commands/env.js.map +1 -1
  61. package/dist/commands/exec.d.ts.map +1 -1
  62. package/dist/commands/exec.js +3 -2
  63. package/dist/commands/exec.js.map +1 -1
  64. package/dist/commands/fleet-asking.d.ts +87 -0
  65. package/dist/commands/fleet-asking.d.ts.map +1 -0
  66. package/dist/commands/fleet-asking.js +176 -0
  67. package/dist/commands/fleet-asking.js.map +1 -0
  68. package/dist/commands/fleet.d.ts +18 -0
  69. package/dist/commands/fleet.d.ts.map +1 -1
  70. package/dist/commands/fleet.js +314 -74
  71. package/dist/commands/fleet.js.map +1 -1
  72. package/dist/commands/health-check.d.ts +8 -6
  73. package/dist/commands/health-check.d.ts.map +1 -1
  74. package/dist/commands/health-check.js +26 -23
  75. package/dist/commands/health-check.js.map +1 -1
  76. package/dist/commands/health.d.ts.map +1 -1
  77. package/dist/commands/health.js +26 -4
  78. package/dist/commands/health.js.map +1 -1
  79. package/dist/commands/infra.d.ts +42 -1
  80. package/dist/commands/infra.d.ts.map +1 -1
  81. package/dist/commands/infra.js +418 -49
  82. package/dist/commands/infra.js.map +1 -1
  83. package/dist/commands/init.d.ts.map +1 -1
  84. package/dist/commands/init.js +21 -36
  85. package/dist/commands/init.js.map +1 -1
  86. package/dist/commands/inspect-graph.d.ts +20 -0
  87. package/dist/commands/inspect-graph.d.ts.map +1 -0
  88. package/dist/commands/inspect-graph.js +74 -0
  89. package/dist/commands/inspect-graph.js.map +1 -0
  90. package/dist/commands/inspect.d.ts.map +1 -1
  91. package/dist/commands/inspect.js +115 -11
  92. package/dist/commands/inspect.js.map +1 -1
  93. package/dist/commands/k8s.d.ts.map +1 -1
  94. package/dist/commands/k8s.js +23 -18
  95. package/dist/commands/k8s.js.map +1 -1
  96. package/dist/commands/kb.d.ts.map +1 -1
  97. package/dist/commands/kb.js +88 -29
  98. package/dist/commands/kb.js.map +1 -1
  99. package/dist/commands/list.d.ts.map +1 -1
  100. package/dist/commands/list.js +25 -3
  101. package/dist/commands/list.js.map +1 -1
  102. package/dist/commands/log-health.d.ts +120 -0
  103. package/dist/commands/log-health.d.ts.map +1 -0
  104. package/dist/commands/log-health.js +212 -0
  105. package/dist/commands/log-health.js.map +1 -0
  106. package/dist/commands/logs.d.ts +96 -2
  107. package/dist/commands/logs.d.ts.map +1 -1
  108. package/dist/commands/logs.js +532 -192
  109. package/dist/commands/logs.js.map +1 -1
  110. package/dist/commands/metrics.d.ts.map +1 -1
  111. package/dist/commands/metrics.js +40 -14
  112. package/dist/commands/metrics.js.map +1 -1
  113. package/dist/commands/monit.d.ts.map +1 -1
  114. package/dist/commands/monit.js +12 -2
  115. package/dist/commands/monit.js.map +1 -1
  116. package/dist/commands/node.d.ts +68 -0
  117. package/dist/commands/node.d.ts.map +1 -1
  118. package/dist/commands/node.js +285 -68
  119. package/dist/commands/node.js.map +1 -1
  120. package/dist/commands/output.d.ts +45 -0
  121. package/dist/commands/output.d.ts.map +1 -0
  122. package/dist/commands/output.js +103 -0
  123. package/dist/commands/output.js.map +1 -0
  124. package/dist/commands/pipeline.d.ts.map +1 -1
  125. package/dist/commands/pipeline.js +26 -19
  126. package/dist/commands/pipeline.js.map +1 -1
  127. package/dist/commands/project.d.ts +19 -0
  128. package/dist/commands/project.d.ts.map +1 -1
  129. package/dist/commands/project.js +125 -27
  130. package/dist/commands/project.js.map +1 -1
  131. package/dist/commands/release-store.d.ts +28 -0
  132. package/dist/commands/release-store.d.ts.map +1 -0
  133. package/dist/commands/release-store.js +158 -0
  134. package/dist/commands/release-store.js.map +1 -0
  135. package/dist/commands/release.d.ts +61 -0
  136. package/dist/commands/release.d.ts.map +1 -0
  137. package/dist/commands/release.js +555 -0
  138. package/dist/commands/release.js.map +1 -0
  139. package/dist/commands/reload.d.ts +16 -0
  140. package/dist/commands/reload.d.ts.map +1 -1
  141. package/dist/commands/reload.js +21 -5
  142. package/dist/commands/reload.js.map +1 -1
  143. package/dist/commands/remote.d.ts +40 -0
  144. package/dist/commands/remote.d.ts.map +1 -1
  145. package/dist/commands/remote.js +146 -35
  146. package/dist/commands/remote.js.map +1 -1
  147. package/dist/commands/restart.d.ts +16 -0
  148. package/dist/commands/restart.d.ts.map +1 -1
  149. package/dist/commands/restart.js +21 -5
  150. package/dist/commands/restart.js.map +1 -1
  151. package/dist/commands/scale.d.ts.map +1 -1
  152. package/dist/commands/scale.js +4 -3
  153. package/dist/commands/scale.js.map +1 -1
  154. package/dist/commands/secret.d.ts +54 -0
  155. package/dist/commands/secret.d.ts.map +1 -1
  156. package/dist/commands/secret.js +236 -34
  157. package/dist/commands/secret.js.map +1 -1
  158. package/dist/commands/service-units.d.ts +181 -0
  159. package/dist/commands/service-units.d.ts.map +1 -0
  160. package/dist/commands/service-units.js +291 -0
  161. package/dist/commands/service-units.js.map +1 -0
  162. package/dist/commands/service.d.ts +39 -0
  163. package/dist/commands/service.d.ts.map +1 -0
  164. package/dist/commands/service.js +370 -0
  165. package/dist/commands/service.js.map +1 -0
  166. package/dist/commands/spinner.d.ts +29 -0
  167. package/dist/commands/spinner.d.ts.map +1 -0
  168. package/dist/commands/spinner.js +44 -0
  169. package/dist/commands/spinner.js.map +1 -0
  170. package/dist/commands/stack.d.ts +49 -1
  171. package/dist/commands/stack.d.ts.map +1 -1
  172. package/dist/commands/stack.js +341 -13
  173. package/dist/commands/stack.js.map +1 -1
  174. package/dist/commands/start.d.ts +16 -0
  175. package/dist/commands/start.d.ts.map +1 -1
  176. package/dist/commands/start.js +20 -3
  177. package/dist/commands/start.js.map +1 -1
  178. package/dist/commands/status.d.ts +9 -0
  179. package/dist/commands/status.d.ts.map +1 -1
  180. package/dist/commands/status.js +62 -29
  181. package/dist/commands/status.js.map +1 -1
  182. package/dist/commands/stop.d.ts +16 -0
  183. package/dist/commands/stop.d.ts.map +1 -1
  184. package/dist/commands/stop.js +34 -6
  185. package/dist/commands/stop.js.map +1 -1
  186. package/dist/commands/tor.d.ts +20 -0
  187. package/dist/commands/tor.d.ts.map +1 -0
  188. package/dist/commands/tor.js +180 -0
  189. package/dist/commands/tor.js.map +1 -0
  190. package/dist/commands/up.d.ts +85 -1
  191. package/dist/commands/up.d.ts.map +1 -1
  192. package/dist/commands/up.js +181 -33
  193. package/dist/commands/up.js.map +1 -1
  194. package/dist/commands/webapp.d.ts.map +1 -1
  195. package/dist/commands/webapp.js +2 -1
  196. package/dist/commands/webapp.js.map +1 -1
  197. package/dist/config/defaults.d.ts +16 -0
  198. package/dist/config/defaults.d.ts.map +1 -1
  199. package/dist/config/defaults.js +26 -3
  200. package/dist/config/defaults.js.map +1 -1
  201. package/dist/config/define-ecosystem.d.ts.map +1 -1
  202. package/dist/config/define-ecosystem.js +2 -0
  203. package/dist/config/define-ecosystem.js.map +1 -1
  204. package/dist/config/index.d.ts +1 -1
  205. package/dist/config/index.d.ts.map +1 -1
  206. package/dist/config/index.js +1 -1
  207. package/dist/config/index.js.map +1 -1
  208. package/dist/config/loader.d.ts +45 -1
  209. package/dist/config/loader.d.ts.map +1 -1
  210. package/dist/config/loader.js +93 -11
  211. package/dist/config/loader.js.map +1 -1
  212. package/dist/config/omnitron-config.schema.d.ts.map +1 -1
  213. package/dist/config/omnitron-config.schema.js +16 -0
  214. package/dist/config/omnitron-config.schema.js.map +1 -1
  215. package/dist/config/types.d.ts +425 -42
  216. package/dist/config/types.d.ts.map +1 -1
  217. package/dist/daemon/config-reload.d.ts +27 -0
  218. package/dist/daemon/config-reload.d.ts.map +1 -0
  219. package/dist/daemon/config-reload.js +42 -0
  220. package/dist/daemon/config-reload.js.map +1 -0
  221. package/dist/daemon/daemon-client.d.ts +150 -2
  222. package/dist/daemon/daemon-client.d.ts.map +1 -1
  223. package/dist/daemon/daemon-client.js +311 -21
  224. package/dist/daemon/daemon-client.js.map +1 -1
  225. package/dist/daemon/daemon-entry.js +92 -38
  226. package/dist/daemon/daemon-entry.js.map +1 -1
  227. package/dist/daemon/daemon-scheduler.d.ts +4 -0
  228. package/dist/daemon/daemon-scheduler.d.ts.map +1 -1
  229. package/dist/daemon/daemon-scheduler.js +137 -7
  230. package/dist/daemon/daemon-scheduler.js.map +1 -1
  231. package/dist/daemon/daemon-state-store.service.d.ts +263 -0
  232. package/dist/daemon/daemon-state-store.service.d.ts.map +1 -0
  233. package/dist/daemon/daemon-state-store.service.js +446 -0
  234. package/dist/daemon/daemon-state-store.service.js.map +1 -0
  235. package/dist/daemon/daemon.d.ts +207 -1
  236. package/dist/daemon/daemon.d.ts.map +1 -1
  237. package/dist/daemon/daemon.js +1254 -143
  238. package/dist/daemon/daemon.js.map +1 -1
  239. package/dist/daemon/daemon.module.d.ts.map +1 -1
  240. package/dist/daemon/daemon.module.js +186 -79
  241. package/dist/daemon/daemon.module.js.map +1 -1
  242. package/dist/daemon/daemon.rpc-service.d.ts +109 -1
  243. package/dist/daemon/daemon.rpc-service.d.ts.map +1 -1
  244. package/dist/daemon/daemon.rpc-service.js +451 -95
  245. package/dist/daemon/daemon.rpc-service.js.map +1 -1
  246. package/dist/daemon/pid-manager.d.ts +69 -5
  247. package/dist/daemon/pid-manager.d.ts.map +1 -1
  248. package/dist/daemon/pid-manager.js +151 -17
  249. package/dist/daemon/pid-manager.js.map +1 -1
  250. package/dist/daemon/spawn-daemon.d.ts +73 -0
  251. package/dist/daemon/spawn-daemon.d.ts.map +1 -0
  252. package/dist/daemon/spawn-daemon.js +101 -0
  253. package/dist/daemon/spawn-daemon.js.map +1 -0
  254. package/dist/daemon/state-store.d.ts +65 -3
  255. package/dist/daemon/state-store.d.ts.map +1 -1
  256. package/dist/daemon/state-store.js +103 -19
  257. package/dist/daemon/state-store.js.map +1 -1
  258. package/dist/database/connection.d.ts +71 -0
  259. package/dist/database/connection.d.ts.map +1 -0
  260. package/dist/database/connection.js +129 -0
  261. package/dist/database/connection.js.map +1 -0
  262. package/dist/database/dialect.d.ts +60 -0
  263. package/dist/database/dialect.d.ts.map +1 -0
  264. package/dist/database/dialect.js +80 -0
  265. package/dist/database/dialect.js.map +1 -0
  266. package/dist/database/migrate.d.ts +5 -2
  267. package/dist/database/migrate.d.ts.map +1 -1
  268. package/dist/database/migrate.js +23 -33
  269. package/dist/database/migrate.js.map +1 -1
  270. package/dist/database/migration-runner.d.ts +50 -0
  271. package/dist/database/migration-runner.d.ts.map +1 -0
  272. package/dist/database/migration-runner.js +143 -0
  273. package/dist/database/migration-runner.js.map +1 -0
  274. package/dist/database/migrations/006_login_throttle.d.ts +17 -0
  275. package/dist/database/migrations/006_login_throttle.d.ts.map +1 -0
  276. package/dist/database/migrations/006_login_throttle.js +33 -0
  277. package/dist/database/migrations/006_login_throttle.js.map +1 -0
  278. package/dist/database/migrations/007_sync_ingested.d.ts +21 -0
  279. package/dist/database/migrations/007_sync_ingested.d.ts.map +1 -0
  280. package/dist/database/migrations/007_sync_ingested.js +39 -0
  281. package/dist/database/migrations/007_sync_ingested.js.map +1 -0
  282. package/dist/database/migrations/008_node_health_version_text.d.ts +24 -0
  283. package/dist/database/migrations/008_node_health_version_text.d.ts.map +1 -0
  284. package/dist/database/migrations/008_node_health_version_text.js +35 -0
  285. package/dist/database/migrations/008_node_health_version_text.js.map +1 -0
  286. package/dist/database/migrations/009_node_health_unmeasured.d.ts +40 -0
  287. package/dist/database/migrations/009_node_health_unmeasured.d.ts.map +1 -0
  288. package/dist/database/migrations/009_node_health_unmeasured.js +63 -0
  289. package/dist/database/migrations/009_node_health_unmeasured.js.map +1 -0
  290. package/dist/database/migrations/010_metrics_raw_had_no_reader.d.ts +22 -0
  291. package/dist/database/migrations/010_metrics_raw_had_no_reader.d.ts.map +1 -0
  292. package/dist/database/migrations/010_metrics_raw_had_no_reader.js +26 -0
  293. package/dist/database/migrations/010_metrics_raw_had_no_reader.js.map +1 -0
  294. package/dist/database/migrations/011_alerts_nobody_had_to_write.d.ts +56 -0
  295. package/dist/database/migrations/011_alerts_nobody_had_to_write.d.ts.map +1 -0
  296. package/dist/database/migrations/011_alerts_nobody_had_to_write.js +79 -0
  297. package/dist/database/migrations/011_alerts_nobody_had_to_write.js.map +1 -0
  298. package/dist/database/migrations/012_a_disk_nobody_watched.d.ts +26 -0
  299. package/dist/database/migrations/012_a_disk_nobody_watched.d.ts.map +1 -0
  300. package/dist/database/migrations/012_a_disk_nobody_watched.js +40 -0
  301. package/dist/database/migrations/012_a_disk_nobody_watched.js.map +1 -0
  302. package/dist/database/migrations/013_an_alarm_delivered.d.ts +14 -0
  303. package/dist/database/migrations/013_an_alarm_delivered.d.ts.map +1 -0
  304. package/dist/database/migrations/013_an_alarm_delivered.js +28 -0
  305. package/dist/database/migrations/013_an_alarm_delivered.js.map +1 -0
  306. package/dist/database/migrations/index.d.ts +21 -0
  307. package/dist/database/migrations/index.d.ts.map +1 -0
  308. package/dist/database/migrations/index.js +47 -0
  309. package/dist/database/migrations/index.js.map +1 -0
  310. package/dist/database/schema.d.ts +27 -11
  311. package/dist/database/schema.d.ts.map +1 -1
  312. package/dist/database/sqlite-date-binding.d.ts +71 -0
  313. package/dist/database/sqlite-date-binding.d.ts.map +1 -0
  314. package/dist/database/sqlite-date-binding.js +174 -0
  315. package/dist/database/sqlite-date-binding.js.map +1 -0
  316. package/dist/execution/data-channel.d.ts +48 -0
  317. package/dist/execution/data-channel.d.ts.map +1 -0
  318. package/dist/execution/data-channel.js +55 -0
  319. package/dist/execution/data-channel.js.map +1 -0
  320. package/dist/execution/execution.service.d.ts +139 -0
  321. package/dist/execution/execution.service.d.ts.map +1 -1
  322. package/dist/execution/execution.service.js +273 -10
  323. package/dist/execution/execution.service.js.map +1 -1
  324. package/dist/index.d.ts +1 -1
  325. package/dist/index.d.ts.map +1 -1
  326. package/dist/infrastructure/bare-metal-plan.d.ts +208 -0
  327. package/dist/infrastructure/bare-metal-plan.d.ts.map +1 -0
  328. package/dist/infrastructure/bare-metal-plan.js +363 -0
  329. package/dist/infrastructure/bare-metal-plan.js.map +1 -0
  330. package/dist/infrastructure/bare-metal-runner.d.ts +65 -0
  331. package/dist/infrastructure/bare-metal-runner.d.ts.map +1 -0
  332. package/dist/infrastructure/bare-metal-runner.js +354 -0
  333. package/dist/infrastructure/bare-metal-runner.js.map +1 -0
  334. package/dist/infrastructure/config-payload.d.ts +149 -0
  335. package/dist/infrastructure/config-payload.d.ts.map +1 -0
  336. package/dist/infrastructure/config-payload.js +235 -0
  337. package/dist/infrastructure/config-payload.js.map +1 -0
  338. package/dist/infrastructure/container-runtime.d.ts +179 -1
  339. package/dist/infrastructure/container-runtime.d.ts.map +1 -1
  340. package/dist/infrastructure/container-runtime.js +612 -45
  341. package/dist/infrastructure/container-runtime.js.map +1 -1
  342. package/dist/infrastructure/gateway-reachability.d.ts +85 -0
  343. package/dist/infrastructure/gateway-reachability.d.ts.map +1 -0
  344. package/dist/infrastructure/gateway-reachability.js +116 -0
  345. package/dist/infrastructure/gateway-reachability.js.map +1 -0
  346. package/dist/infrastructure/gateway-redis-db.d.ts +29 -0
  347. package/dist/infrastructure/gateway-redis-db.d.ts.map +1 -0
  348. package/dist/infrastructure/gateway-redis-db.js +32 -0
  349. package/dist/infrastructure/gateway-redis-db.js.map +1 -0
  350. package/dist/infrastructure/host-inspection.d.ts +223 -0
  351. package/dist/infrastructure/host-inspection.d.ts.map +1 -0
  352. package/dist/infrastructure/host-inspection.js +501 -0
  353. package/dist/infrastructure/host-inspection.js.map +1 -0
  354. package/dist/infrastructure/infrastructure-gate.d.ts.map +1 -1
  355. package/dist/infrastructure/infrastructure.service.d.ts +247 -6
  356. package/dist/infrastructure/infrastructure.service.d.ts.map +1 -1
  357. package/dist/infrastructure/infrastructure.service.js +571 -96
  358. package/dist/infrastructure/infrastructure.service.js.map +1 -1
  359. package/dist/infrastructure/known-machines.d.ts +76 -0
  360. package/dist/infrastructure/known-machines.d.ts.map +1 -0
  361. package/dist/infrastructure/known-machines.js +94 -0
  362. package/dist/infrastructure/known-machines.js.map +1 -0
  363. package/dist/infrastructure/node-credentials.d.ts +45 -0
  364. package/dist/infrastructure/node-credentials.d.ts.map +1 -0
  365. package/dist/infrastructure/node-credentials.js +80 -0
  366. package/dist/infrastructure/node-credentials.js.map +1 -0
  367. package/dist/infrastructure/orphan-containers.d.ts +99 -0
  368. package/dist/infrastructure/orphan-containers.d.ts.map +1 -0
  369. package/dist/infrastructure/orphan-containers.js +106 -0
  370. package/dist/infrastructure/orphan-containers.js.map +1 -0
  371. package/dist/infrastructure/phantom-endpoint-janitor.d.ts +92 -0
  372. package/dist/infrastructure/phantom-endpoint-janitor.d.ts.map +1 -0
  373. package/dist/infrastructure/phantom-endpoint-janitor.js +199 -0
  374. package/dist/infrastructure/phantom-endpoint-janitor.js.map +1 -0
  375. package/dist/infrastructure/presets/gateway-openresty.d.ts.map +1 -1
  376. package/dist/infrastructure/presets/gateway-openresty.js +29 -3
  377. package/dist/infrastructure/presets/gateway-openresty.js.map +1 -1
  378. package/dist/infrastructure/presets/index.d.ts.map +1 -1
  379. package/dist/infrastructure/presets/index.js +2 -0
  380. package/dist/infrastructure/presets/index.js.map +1 -1
  381. package/dist/infrastructure/presets/minio.d.ts.map +1 -1
  382. package/dist/infrastructure/presets/minio.js +36 -3
  383. package/dist/infrastructure/presets/minio.js.map +1 -1
  384. package/dist/infrastructure/presets/postgres.d.ts.map +1 -1
  385. package/dist/infrastructure/presets/postgres.js +78 -5
  386. package/dist/infrastructure/presets/postgres.js.map +1 -1
  387. package/dist/infrastructure/presets/redis.d.ts.map +1 -1
  388. package/dist/infrastructure/presets/redis.js +23 -4
  389. package/dist/infrastructure/presets/redis.js.map +1 -1
  390. package/dist/infrastructure/presets/registry.d.ts.map +1 -1
  391. package/dist/infrastructure/presets/registry.js +85 -4
  392. package/dist/infrastructure/presets/registry.js.map +1 -1
  393. package/dist/infrastructure/presets/tor.d.ts +112 -0
  394. package/dist/infrastructure/presets/tor.d.ts.map +1 -0
  395. package/dist/infrastructure/presets/tor.js +185 -0
  396. package/dist/infrastructure/presets/tor.js.map +1 -0
  397. package/dist/infrastructure/presets/torrc.d.ts +54 -0
  398. package/dist/infrastructure/presets/torrc.d.ts.map +1 -0
  399. package/dist/infrastructure/presets/torrc.js +153 -0
  400. package/dist/infrastructure/presets/torrc.js.map +1 -0
  401. package/dist/infrastructure/presets/types.d.ts +17 -0
  402. package/dist/infrastructure/presets/types.d.ts.map +1 -1
  403. package/dist/infrastructure/provisioning-outcome.d.ts +85 -0
  404. package/dist/infrastructure/provisioning-outcome.d.ts.map +1 -0
  405. package/dist/infrastructure/provisioning-outcome.js +122 -0
  406. package/dist/infrastructure/provisioning-outcome.js.map +1 -0
  407. package/dist/infrastructure/server-registry.d.ts +27 -0
  408. package/dist/infrastructure/server-registry.d.ts.map +1 -1
  409. package/dist/infrastructure/server-registry.js +60 -5
  410. package/dist/infrastructure/server-registry.js.map +1 -1
  411. package/dist/infrastructure/service-binding.d.ts +60 -0
  412. package/dist/infrastructure/service-binding.d.ts.map +1 -0
  413. package/dist/infrastructure/service-binding.js +90 -0
  414. package/dist/infrastructure/service-binding.js.map +1 -0
  415. package/dist/infrastructure/service-credentials.d.ts +105 -0
  416. package/dist/infrastructure/service-credentials.d.ts.map +1 -0
  417. package/dist/infrastructure/service-credentials.js +141 -0
  418. package/dist/infrastructure/service-credentials.js.map +1 -0
  419. package/dist/infrastructure/service-resolver.d.ts +191 -12
  420. package/dist/infrastructure/service-resolver.d.ts.map +1 -1
  421. package/dist/infrastructure/service-resolver.js +521 -60
  422. package/dist/infrastructure/service-resolver.js.map +1 -1
  423. package/dist/infrastructure/shipped-config.d.ts +43 -0
  424. package/dist/infrastructure/shipped-config.d.ts.map +1 -0
  425. package/dist/infrastructure/shipped-config.js +159 -0
  426. package/dist/infrastructure/shipped-config.js.map +1 -0
  427. package/dist/infrastructure/stack-infra-manager.d.ts +7 -1
  428. package/dist/infrastructure/stack-infra-manager.d.ts.map +1 -1
  429. package/dist/infrastructure/stack-infra-manager.js +32 -14
  430. package/dist/infrastructure/stack-infra-manager.js.map +1 -1
  431. package/dist/infrastructure/types.d.ts +278 -6
  432. package/dist/infrastructure/types.d.ts.map +1 -1
  433. package/dist/mcp/mcp-bridge.d.ts.map +1 -1
  434. package/dist/mcp/mcp-bridge.js.map +1 -1
  435. package/dist/mcp/tool-groups/apps.tools.d.ts +2 -1
  436. package/dist/mcp/tool-groups/apps.tools.d.ts.map +1 -1
  437. package/dist/mcp/tool-groups/apps.tools.js +2 -2
  438. package/dist/mcp/tool-groups/apps.tools.js.map +1 -1
  439. package/dist/mcp/tool-groups/infra.tools.d.ts +16 -2
  440. package/dist/mcp/tool-groups/infra.tools.d.ts.map +1 -1
  441. package/dist/mcp/tool-groups/infra.tools.js +51 -41
  442. package/dist/mcp/tool-groups/infra.tools.js.map +1 -1
  443. package/dist/mcp/tool-groups/kb.tools.d.ts.map +1 -1
  444. package/dist/mcp/tool-groups/kb.tools.js +4 -6
  445. package/dist/mcp/tool-groups/kb.tools.js.map +1 -1
  446. package/dist/mcp/tool-groups/management.tools.d.ts +20 -3
  447. package/dist/mcp/tool-groups/management.tools.d.ts.map +1 -1
  448. package/dist/mcp/tool-groups/management.tools.js +158 -125
  449. package/dist/mcp/tool-groups/management.tools.js.map +1 -1
  450. package/dist/mcp/tool-groups/monitoring.tools.d.ts +10 -1
  451. package/dist/mcp/tool-groups/monitoring.tools.d.ts.map +1 -1
  452. package/dist/mcp/tool-groups/monitoring.tools.js +65 -18
  453. package/dist/mcp/tool-groups/monitoring.tools.js.map +1 -1
  454. package/dist/mcp/unavailable-tools.d.ts +35 -0
  455. package/dist/mcp/unavailable-tools.d.ts.map +1 -0
  456. package/dist/mcp/unavailable-tools.js +59 -0
  457. package/dist/mcp/unavailable-tools.js.map +1 -0
  458. package/dist/monitoring/app-health.indicator.d.ts.map +1 -1
  459. package/dist/monitoring/app-health.indicator.js +12 -0
  460. package/dist/monitoring/app-health.indicator.js.map +1 -1
  461. package/dist/monitoring/desktop-notifier.d.ts +26 -0
  462. package/dist/monitoring/desktop-notifier.d.ts.map +1 -0
  463. package/dist/monitoring/desktop-notifier.js +49 -0
  464. package/dist/monitoring/desktop-notifier.js.map +1 -0
  465. package/dist/monitoring/docker-health.indicator.d.ts +17 -1
  466. package/dist/monitoring/docker-health.indicator.d.ts.map +1 -1
  467. package/dist/monitoring/docker-health.indicator.js +38 -8
  468. package/dist/monitoring/docker-health.indicator.js.map +1 -1
  469. package/dist/monitoring/event-loop-stall.indicator.d.ts +26 -0
  470. package/dist/monitoring/event-loop-stall.indicator.d.ts.map +1 -0
  471. package/dist/monitoring/event-loop-stall.indicator.js +47 -0
  472. package/dist/monitoring/event-loop-stall.indicator.js.map +1 -0
  473. package/dist/monitoring/event-loop-watch.d.ts +124 -0
  474. package/dist/monitoring/event-loop-watch.d.ts.map +1 -0
  475. package/dist/monitoring/event-loop-watch.js +179 -0
  476. package/dist/monitoring/event-loop-watch.js.map +1 -0
  477. package/dist/monitoring/host-disk.d.ts +6 -0
  478. package/dist/monitoring/host-disk.d.ts.map +1 -0
  479. package/dist/monitoring/host-disk.js +26 -0
  480. package/dist/monitoring/host-disk.js.map +1 -0
  481. package/dist/monitoring/log-line.d.ts +188 -0
  482. package/dist/monitoring/log-line.d.ts.map +1 -0
  483. package/dist/monitoring/log-line.js +458 -0
  484. package/dist/monitoring/log-line.js.map +1 -0
  485. package/dist/monitoring/log-manager.d.ts +89 -8
  486. package/dist/monitoring/log-manager.d.ts.map +1 -1
  487. package/dist/monitoring/log-manager.js +246 -77
  488. package/dist/monitoring/log-manager.js.map +1 -1
  489. package/dist/observability/index.d.ts +4 -0
  490. package/dist/observability/index.d.ts.map +1 -0
  491. package/dist/observability/index.js +3 -0
  492. package/dist/observability/index.js.map +1 -0
  493. package/dist/observability/metrics-bridge.d.ts +87 -0
  494. package/dist/observability/metrics-bridge.d.ts.map +1 -0
  495. package/dist/observability/metrics-bridge.js +295 -0
  496. package/dist/observability/metrics-bridge.js.map +1 -0
  497. package/dist/observability/metrics-server.d.ts +68 -0
  498. package/dist/observability/metrics-server.d.ts.map +1 -0
  499. package/dist/observability/metrics-server.js +146 -0
  500. package/dist/observability/metrics-server.js.map +1 -0
  501. package/dist/orchestrator/app-handle.d.ts +170 -3
  502. package/dist/orchestrator/app-handle.d.ts.map +1 -1
  503. package/dist/orchestrator/app-handle.js +177 -3
  504. package/dist/orchestrator/app-handle.js.map +1 -1
  505. package/dist/orchestrator/app-health.d.ts +33 -0
  506. package/dist/orchestrator/app-health.d.ts.map +1 -0
  507. package/dist/orchestrator/app-health.js +74 -0
  508. package/dist/orchestrator/app-health.js.map +1 -0
  509. package/dist/orchestrator/app-traffic.d.ts +14 -0
  510. package/dist/orchestrator/app-traffic.d.ts.map +1 -0
  511. package/dist/orchestrator/app-traffic.js +33 -0
  512. package/dist/orchestrator/app-traffic.js.map +1 -0
  513. package/dist/orchestrator/bootstrap-loader-child.d.ts +19 -0
  514. package/dist/orchestrator/bootstrap-loader-child.d.ts.map +1 -0
  515. package/dist/orchestrator/bootstrap-loader-child.js +43 -0
  516. package/dist/orchestrator/bootstrap-loader-child.js.map +1 -0
  517. package/dist/orchestrator/bootstrap-loader.d.ts +72 -0
  518. package/dist/orchestrator/bootstrap-loader.d.ts.map +1 -1
  519. package/dist/orchestrator/bootstrap-loader.js +350 -5
  520. package/dist/orchestrator/bootstrap-loader.js.map +1 -1
  521. package/dist/orchestrator/bootstrap-process.d.ts +148 -4
  522. package/dist/orchestrator/bootstrap-process.d.ts.map +1 -1
  523. package/dist/orchestrator/bootstrap-process.js +496 -18
  524. package/dist/orchestrator/bootstrap-process.js.map +1 -1
  525. package/dist/orchestrator/build-service.d.ts +50 -3
  526. package/dist/orchestrator/build-service.d.ts.map +1 -1
  527. package/dist/orchestrator/build-service.js +357 -85
  528. package/dist/orchestrator/build-service.js.map +1 -1
  529. package/dist/orchestrator/call-exposed-service.d.ts +7 -0
  530. package/dist/orchestrator/call-exposed-service.d.ts.map +1 -0
  531. package/dist/orchestrator/call-exposed-service.js +50 -0
  532. package/dist/orchestrator/call-exposed-service.js.map +1 -0
  533. package/dist/orchestrator/classic-launcher.d.ts +1 -0
  534. package/dist/orchestrator/classic-launcher.d.ts.map +1 -1
  535. package/dist/orchestrator/classic-launcher.js +34 -3
  536. package/dist/orchestrator/classic-launcher.js.map +1 -1
  537. package/dist/orchestrator/file-watcher.d.ts +78 -1
  538. package/dist/orchestrator/file-watcher.d.ts.map +1 -1
  539. package/dist/orchestrator/file-watcher.js +240 -43
  540. package/dist/orchestrator/file-watcher.js.map +1 -1
  541. package/dist/orchestrator/module-worker-process.d.ts.map +1 -1
  542. package/dist/orchestrator/module-worker-process.js +10 -0
  543. package/dist/orchestrator/module-worker-process.js.map +1 -1
  544. package/dist/orchestrator/orchestrator.service.d.ts +540 -7
  545. package/dist/orchestrator/orchestrator.service.d.ts.map +1 -1
  546. package/dist/orchestrator/orchestrator.service.js +2106 -242
  547. package/dist/orchestrator/orchestrator.service.js.map +1 -1
  548. package/dist/orchestrator/owned-pids.d.ts +83 -0
  549. package/dist/orchestrator/owned-pids.d.ts.map +1 -0
  550. package/dist/orchestrator/owned-pids.js +93 -0
  551. package/dist/orchestrator/owned-pids.js.map +1 -0
  552. package/dist/orchestrator/port-conflict.d.ts +102 -0
  553. package/dist/orchestrator/port-conflict.d.ts.map +1 -0
  554. package/dist/orchestrator/port-conflict.js +131 -0
  555. package/dist/orchestrator/port-conflict.js.map +1 -0
  556. package/dist/orchestrator/process-janitor.d.ts +227 -0
  557. package/dist/orchestrator/process-janitor.d.ts.map +1 -0
  558. package/dist/orchestrator/process-janitor.js +495 -0
  559. package/dist/orchestrator/process-janitor.js.map +1 -0
  560. package/dist/orchestrator/ps-metrics.d.ts +37 -0
  561. package/dist/orchestrator/ps-metrics.d.ts.map +1 -0
  562. package/dist/orchestrator/ps-metrics.js +60 -0
  563. package/dist/orchestrator/ps-metrics.js.map +1 -0
  564. package/dist/orchestrator/service-router.d.ts +58 -2
  565. package/dist/orchestrator/service-router.d.ts.map +1 -1
  566. package/dist/orchestrator/service-router.js +157 -25
  567. package/dist/orchestrator/service-router.js.map +1 -1
  568. package/dist/orchestrator/topology-query.d.ts +49 -0
  569. package/dist/orchestrator/topology-query.d.ts.map +1 -0
  570. package/dist/orchestrator/topology-query.js +54 -0
  571. package/dist/orchestrator/topology-query.js.map +1 -0
  572. package/dist/project/artifact-builder.d.ts +174 -3
  573. package/dist/project/artifact-builder.d.ts.map +1 -1
  574. package/dist/project/artifact-builder.js +454 -42
  575. package/dist/project/artifact-builder.js.map +1 -1
  576. package/dist/project/build-decision.d.ts +58 -0
  577. package/dist/project/build-decision.d.ts.map +1 -0
  578. package/dist/project/build-decision.js +59 -0
  579. package/dist/project/build-decision.js.map +1 -0
  580. package/dist/project/config-resolver.d.ts +6 -4
  581. package/dist/project/config-resolver.d.ts.map +1 -1
  582. package/dist/project/config-resolver.js +158 -78
  583. package/dist/project/config-resolver.js.map +1 -1
  584. package/dist/project/declared-config.d.ts +42 -0
  585. package/dist/project/declared-config.d.ts.map +1 -0
  586. package/dist/project/declared-config.js +60 -0
  587. package/dist/project/declared-config.js.map +1 -0
  588. package/dist/project/dependency-analyzer.d.ts.map +1 -1
  589. package/dist/project/dependency-analyzer.js.map +1 -1
  590. package/dist/project/deploy-phases.d.ts +35 -0
  591. package/dist/project/deploy-phases.d.ts.map +1 -0
  592. package/dist/project/deploy-phases.js +75 -0
  593. package/dist/project/deploy-phases.js.map +1 -0
  594. package/dist/project/exec-in-group.d.ts +49 -0
  595. package/dist/project/exec-in-group.d.ts.map +1 -0
  596. package/dist/project/exec-in-group.js +100 -0
  597. package/dist/project/exec-in-group.js.map +1 -0
  598. package/dist/project/node-app-config.d.ts +101 -0
  599. package/dist/project/node-app-config.d.ts.map +1 -0
  600. package/dist/project/node-app-config.js +134 -0
  601. package/dist/project/node-app-config.js.map +1 -0
  602. package/dist/project/node-app-health.d.ts +76 -0
  603. package/dist/project/node-app-health.d.ts.map +1 -0
  604. package/dist/project/node-app-health.js +119 -0
  605. package/dist/project/node-app-health.js.map +1 -0
  606. package/dist/project/operator-account.d.ts +287 -0
  607. package/dist/project/operator-account.d.ts.map +1 -0
  608. package/dist/project/operator-account.js +373 -0
  609. package/dist/project/operator-account.js.map +1 -0
  610. package/dist/project/registry.d.ts +46 -8
  611. package/dist/project/registry.d.ts.map +1 -1
  612. package/dist/project/registry.js +238 -40
  613. package/dist/project/registry.js.map +1 -1
  614. package/dist/project/requirements-scanner.d.ts +1 -0
  615. package/dist/project/requirements-scanner.d.ts.map +1 -1
  616. package/dist/project/requirements-scanner.js +28 -3
  617. package/dist/project/requirements-scanner.js.map +1 -1
  618. package/dist/project/stack-env.d.ts +37 -0
  619. package/dist/project/stack-env.d.ts.map +1 -0
  620. package/dist/project/stack-env.js +85 -0
  621. package/dist/project/stack-env.js.map +1 -0
  622. package/dist/project/stand-containers.d.ts +4 -0
  623. package/dist/project/stand-containers.d.ts.map +1 -0
  624. package/dist/project/stand-containers.js +27 -0
  625. package/dist/project/stand-containers.js.map +1 -0
  626. package/dist/project/working-tree.d.ts +62 -0
  627. package/dist/project/working-tree.d.ts.map +1 -0
  628. package/dist/project/working-tree.js +101 -0
  629. package/dist/project/working-tree.js.map +1 -0
  630. package/dist/release/artifact-store.d.ts +360 -0
  631. package/dist/release/artifact-store.d.ts.map +1 -0
  632. package/dist/release/artifact-store.js +1040 -0
  633. package/dist/release/artifact-store.js.map +1 -0
  634. package/dist/release/attest-on-node.d.ts +92 -0
  635. package/dist/release/attest-on-node.d.ts.map +1 -0
  636. package/dist/release/attest-on-node.js +207 -0
  637. package/dist/release/attest-on-node.js.map +1 -0
  638. package/dist/release/attest.d.ts +135 -0
  639. package/dist/release/attest.d.ts.map +1 -0
  640. package/dist/release/attest.js +199 -0
  641. package/dist/release/attest.js.map +1 -0
  642. package/dist/release/build-run.d.ts +151 -0
  643. package/dist/release/build-run.d.ts.map +1 -0
  644. package/dist/release/build-run.js +609 -0
  645. package/dist/release/build-run.js.map +1 -0
  646. package/dist/release/builder.d.ts +57 -0
  647. package/dist/release/builder.d.ts.map +1 -0
  648. package/dist/release/builder.js +120 -0
  649. package/dist/release/builder.js.map +1 -0
  650. package/dist/release/daemon-omni.d.ts +41 -0
  651. package/dist/release/daemon-omni.d.ts.map +1 -0
  652. package/dist/release/daemon-omni.js +59 -0
  653. package/dist/release/daemon-omni.js.map +1 -0
  654. package/dist/release/definition-inputs.d.ts +34 -0
  655. package/dist/release/definition-inputs.d.ts.map +1 -0
  656. package/dist/release/definition-inputs.js +90 -0
  657. package/dist/release/definition-inputs.js.map +1 -0
  658. package/dist/release/delivered.d.ts +53 -0
  659. package/dist/release/delivered.d.ts.map +1 -0
  660. package/dist/release/delivered.js +81 -0
  661. package/dist/release/delivered.js.map +1 -0
  662. package/dist/release/layout.d.ts +61 -0
  663. package/dist/release/layout.d.ts.map +1 -0
  664. package/dist/release/layout.js +114 -0
  665. package/dist/release/layout.js.map +1 -0
  666. package/dist/release/load.d.ts +44 -0
  667. package/dist/release/load.d.ts.map +1 -0
  668. package/dist/release/load.js +84 -0
  669. package/dist/release/load.js.map +1 -0
  670. package/dist/release/manifest.d.ts +299 -0
  671. package/dist/release/manifest.d.ts.map +1 -0
  672. package/dist/release/manifest.js +176 -0
  673. package/dist/release/manifest.js.map +1 -0
  674. package/dist/release/migrations.d.ts +32 -0
  675. package/dist/release/migrations.d.ts.map +1 -0
  676. package/dist/release/migrations.js +51 -0
  677. package/dist/release/migrations.js.map +1 -0
  678. package/dist/release/publish.d.ts +71 -0
  679. package/dist/release/publish.d.ts.map +1 -0
  680. package/dist/release/publish.js +102 -0
  681. package/dist/release/publish.js.map +1 -0
  682. package/dist/release/store.d.ts +174 -0
  683. package/dist/release/store.d.ts.map +1 -0
  684. package/dist/release/store.js +257 -0
  685. package/dist/release/store.js.map +1 -0
  686. package/dist/services/alert.rpc-service.d.ts +11 -15
  687. package/dist/services/alert.rpc-service.d.ts.map +1 -1
  688. package/dist/services/alert.rpc-service.js +29 -14
  689. package/dist/services/alert.rpc-service.js.map +1 -1
  690. package/dist/services/alert.service.d.ts +96 -59
  691. package/dist/services/alert.service.d.ts.map +1 -1
  692. package/dist/services/alert.service.js +455 -70
  693. package/dist/services/alert.service.js.map +1 -1
  694. package/dist/services/anonymous-input.d.ts +26 -0
  695. package/dist/services/anonymous-input.d.ts.map +1 -0
  696. package/dist/services/anonymous-input.js +44 -0
  697. package/dist/services/anonymous-input.js.map +1 -0
  698. package/dist/services/audit.rpc-service.d.ts +27 -0
  699. package/dist/services/audit.rpc-service.d.ts.map +1 -0
  700. package/dist/services/audit.rpc-service.js +57 -0
  701. package/dist/services/audit.rpc-service.js.map +1 -0
  702. package/dist/services/audit.service.d.ts +165 -0
  703. package/dist/services/audit.service.d.ts.map +1 -0
  704. package/dist/services/audit.service.js +242 -0
  705. package/dist/services/audit.service.js.map +1 -0
  706. package/dist/services/auth-context.d.ts +21 -1
  707. package/dist/services/auth-context.d.ts.map +1 -1
  708. package/dist/services/auth-context.js +51 -5
  709. package/dist/services/auth-context.js.map +1 -1
  710. package/dist/services/auth.rpc-service.d.ts +0 -1
  711. package/dist/services/auth.rpc-service.d.ts.map +1 -1
  712. package/dist/services/auth.rpc-service.js +23 -9
  713. package/dist/services/auth.rpc-service.js.map +1 -1
  714. package/dist/services/auth.service.d.ts +47 -33
  715. package/dist/services/auth.service.d.ts.map +1 -1
  716. package/dist/services/auth.service.js +163 -24
  717. package/dist/services/auth.service.js.map +1 -1
  718. package/dist/services/backup-pipeline.d.ts +97 -0
  719. package/dist/services/backup-pipeline.d.ts.map +1 -0
  720. package/dist/services/backup-pipeline.js +286 -0
  721. package/dist/services/backup-pipeline.js.map +1 -0
  722. package/dist/services/backup-schedule.d.ts +69 -0
  723. package/dist/services/backup-schedule.d.ts.map +1 -0
  724. package/dist/services/backup-schedule.js +132 -0
  725. package/dist/services/backup-schedule.js.map +1 -0
  726. package/dist/services/backup.rpc-service.d.ts +31 -2
  727. package/dist/services/backup.rpc-service.d.ts.map +1 -1
  728. package/dist/services/backup.rpc-service.js +53 -0
  729. package/dist/services/backup.rpc-service.js.map +1 -1
  730. package/dist/services/backup.service.d.ts +458 -14
  731. package/dist/services/backup.service.d.ts.map +1 -1
  732. package/dist/services/backup.service.js +1368 -170
  733. package/dist/services/backup.service.js.map +1 -1
  734. package/dist/services/bundle-build-worker.d.ts +19 -0
  735. package/dist/services/bundle-build-worker.d.ts.map +1 -0
  736. package/dist/services/bundle-build-worker.js +40 -0
  737. package/dist/services/bundle-build-worker.js.map +1 -0
  738. package/dist/services/bundle-builder.d.ts +487 -0
  739. package/dist/services/bundle-builder.d.ts.map +1 -0
  740. package/dist/services/bundle-builder.js +1083 -0
  741. package/dist/services/bundle-builder.js.map +1 -0
  742. package/dist/services/bundle-worker-protocol.d.ts +19 -0
  743. package/dist/services/bundle-worker-protocol.d.ts.map +1 -0
  744. package/dist/services/bundle-worker-protocol.js +32 -0
  745. package/dist/services/bundle-worker-protocol.js.map +1 -0
  746. package/dist/services/deploy.rpc-service.d.ts +4 -1
  747. package/dist/services/deploy.rpc-service.d.ts.map +1 -1
  748. package/dist/services/deploy.rpc-service.js +10 -0
  749. package/dist/services/deploy.rpc-service.js.map +1 -1
  750. package/dist/services/deploy.service.d.ts +14 -24
  751. package/dist/services/deploy.service.d.ts.map +1 -1
  752. package/dist/services/deploy.service.js +46 -5
  753. package/dist/services/deploy.service.js.map +1 -1
  754. package/dist/services/discovery.rpc-service.d.ts +2 -1
  755. package/dist/services/discovery.rpc-service.d.ts.map +1 -1
  756. package/dist/services/discovery.rpc-service.js.map +1 -1
  757. package/dist/services/discovery.service.d.ts +32 -28
  758. package/dist/services/discovery.service.d.ts.map +1 -1
  759. package/dist/services/discovery.service.js +108 -133
  760. package/dist/services/discovery.service.js.map +1 -1
  761. package/dist/services/event-broadcaster.rpc-service.d.ts +36 -23
  762. package/dist/services/event-broadcaster.rpc-service.d.ts.map +1 -1
  763. package/dist/services/event-broadcaster.rpc-service.js +70 -32
  764. package/dist/services/event-broadcaster.rpc-service.js.map +1 -1
  765. package/dist/services/event-broadcaster.service.d.ts.map +1 -1
  766. package/dist/services/event-broadcaster.service.js.map +1 -1
  767. package/dist/services/fleet.rpc-service.d.ts +2 -1
  768. package/dist/services/fleet.rpc-service.d.ts.map +1 -1
  769. package/dist/services/fleet.rpc-service.js +3 -1
  770. package/dist/services/fleet.rpc-service.js.map +1 -1
  771. package/dist/services/fleet.service.d.ts +32 -34
  772. package/dist/services/fleet.service.d.ts.map +1 -1
  773. package/dist/services/fleet.service.js +66 -10
  774. package/dist/services/fleet.service.js.map +1 -1
  775. package/dist/services/health-check.rpc-service.d.ts +2 -1
  776. package/dist/services/health-check.rpc-service.d.ts.map +1 -1
  777. package/dist/services/health-check.rpc-service.js.map +1 -1
  778. package/dist/services/health-check.service.d.ts +50 -36
  779. package/dist/services/health-check.service.d.ts.map +1 -1
  780. package/dist/services/health-check.service.js +179 -182
  781. package/dist/services/health-check.service.js.map +1 -1
  782. package/dist/services/infrastructure.rpc-service.d.ts +297 -2
  783. package/dist/services/infrastructure.rpc-service.d.ts.map +1 -1
  784. package/dist/services/infrastructure.rpc-service.js +523 -11
  785. package/dist/services/infrastructure.rpc-service.js.map +1 -1
  786. package/dist/services/kubernetes.rpc-service.d.ts +2 -1
  787. package/dist/services/kubernetes.rpc-service.d.ts.map +1 -1
  788. package/dist/services/kubernetes.rpc-service.js.map +1 -1
  789. package/dist/services/kubernetes.service.d.ts +5 -39
  790. package/dist/services/kubernetes.service.d.ts.map +1 -1
  791. package/dist/services/kubernetes.service.js +29 -5
  792. package/dist/services/kubernetes.service.js.map +1 -1
  793. package/dist/services/local-bundle.d.ts +151 -0
  794. package/dist/services/local-bundle.d.ts.map +1 -0
  795. package/dist/services/local-bundle.js +233 -0
  796. package/dist/services/local-bundle.js.map +1 -0
  797. package/dist/services/lockout.d.ts +28 -0
  798. package/dist/services/lockout.d.ts.map +1 -0
  799. package/dist/services/lockout.js +41 -0
  800. package/dist/services/lockout.js.map +1 -0
  801. package/dist/services/log-collector.rpc-service.d.ts +16 -0
  802. package/dist/services/log-collector.rpc-service.d.ts.map +1 -1
  803. package/dist/services/log-collector.rpc-service.js +16 -0
  804. package/dist/services/log-collector.rpc-service.js.map +1 -1
  805. package/dist/services/log-collector.service.d.ts +172 -54
  806. package/dist/services/log-collector.service.d.ts.map +1 -1
  807. package/dist/services/log-collector.service.js +492 -102
  808. package/dist/services/log-collector.service.js.map +1 -1
  809. package/dist/services/log-retention.d.ts +50 -0
  810. package/dist/services/log-retention.d.ts.map +1 -0
  811. package/dist/services/log-retention.js +52 -0
  812. package/dist/services/log-retention.js.map +1 -0
  813. package/dist/services/maintenance-lock.d.ts +162 -0
  814. package/dist/services/maintenance-lock.d.ts.map +1 -0
  815. package/dist/services/maintenance-lock.js +316 -0
  816. package/dist/services/maintenance-lock.js.map +1 -0
  817. package/dist/services/master-address.d.ts +107 -0
  818. package/dist/services/master-address.d.ts.map +1 -0
  819. package/dist/services/master-address.js +154 -0
  820. package/dist/services/master-address.js.map +1 -0
  821. package/dist/services/migration-output.d.ts +16 -0
  822. package/dist/services/migration-output.d.ts.map +1 -0
  823. package/dist/services/migration-output.js +22 -0
  824. package/dist/services/migration-output.js.map +1 -0
  825. package/dist/services/netron-telemetry-transport.d.ts.map +1 -1
  826. package/dist/services/netron-telemetry-transport.js +0 -4
  827. package/dist/services/netron-telemetry-transport.js.map +1 -1
  828. package/dist/services/node-deploy-lease.d.ts +154 -0
  829. package/dist/services/node-deploy-lease.d.ts.map +1 -0
  830. package/dist/services/node-deploy-lease.js +386 -0
  831. package/dist/services/node-deploy-lease.js.map +1 -0
  832. package/dist/services/node-health.repository.d.ts +63 -4
  833. package/dist/services/node-health.repository.d.ts.map +1 -1
  834. package/dist/services/node-health.repository.js +108 -67
  835. package/dist/services/node-health.repository.js.map +1 -1
  836. package/dist/services/node-manager.rpc-service.d.ts +355 -10
  837. package/dist/services/node-manager.rpc-service.d.ts.map +1 -1
  838. package/dist/services/node-manager.rpc-service.js +730 -34
  839. package/dist/services/node-manager.rpc-service.js.map +1 -1
  840. package/dist/services/node-manager.service.d.ts +267 -95
  841. package/dist/services/node-manager.service.d.ts.map +1 -1
  842. package/dist/services/node-manager.service.js +806 -104
  843. package/dist/services/node-manager.service.js.map +1 -1
  844. package/dist/services/node-upgrade.d.ts +129 -0
  845. package/dist/services/node-upgrade.d.ts.map +1 -0
  846. package/dist/services/node-upgrade.js +161 -0
  847. package/dist/services/node-upgrade.js.map +1 -0
  848. package/dist/services/node-upgrade.service.d.ts +232 -0
  849. package/dist/services/node-upgrade.service.d.ts.map +1 -0
  850. package/dist/services/node-upgrade.service.js +468 -0
  851. package/dist/services/node-upgrade.service.js.map +1 -0
  852. package/dist/services/pipeline.rpc-service.d.ts +2 -1
  853. package/dist/services/pipeline.rpc-service.d.ts.map +1 -1
  854. package/dist/services/pipeline.rpc-service.js.map +1 -1
  855. package/dist/services/pipeline.service.d.ts +30 -46
  856. package/dist/services/pipeline.service.d.ts.map +1 -1
  857. package/dist/services/pipeline.service.js +125 -11
  858. package/dist/services/pipeline.service.js.map +1 -1
  859. package/dist/services/project.rpc-service.d.ts +137 -5
  860. package/dist/services/project.rpc-service.d.ts.map +1 -1
  861. package/dist/services/project.rpc-service.js +258 -22
  862. package/dist/services/project.rpc-service.js.map +1 -1
  863. package/dist/services/project.service.d.ts +680 -9
  864. package/dist/services/project.service.d.ts.map +1 -1
  865. package/dist/services/project.service.js +2914 -293
  866. package/dist/services/project.service.js.map +1 -1
  867. package/dist/services/redeploy-decision.d.ts +176 -0
  868. package/dist/services/redeploy-decision.d.ts.map +1 -0
  869. package/dist/services/redeploy-decision.js +142 -0
  870. package/dist/services/redeploy-decision.js.map +1 -0
  871. package/dist/services/release.rpc-service.d.ts +159 -0
  872. package/dist/services/release.rpc-service.d.ts.map +1 -0
  873. package/dist/services/release.rpc-service.js +395 -0
  874. package/dist/services/release.rpc-service.js.map +1 -0
  875. package/dist/services/release.service.d.ts +114 -0
  876. package/dist/services/release.service.d.ts.map +1 -0
  877. package/dist/services/release.service.js +208 -0
  878. package/dist/services/release.service.js.map +1 -0
  879. package/dist/services/remote-deployer.service.d.ts +569 -8
  880. package/dist/services/remote-deployer.service.d.ts.map +1 -1
  881. package/dist/services/remote-deployer.service.js +1618 -169
  882. package/dist/services/remote-deployer.service.js.map +1 -1
  883. package/dist/services/remote-ops.service.d.ts +51 -9
  884. package/dist/services/remote-ops.service.d.ts.map +1 -1
  885. package/dist/services/remote-ops.service.js +235 -39
  886. package/dist/services/remote-ops.service.js.map +1 -1
  887. package/dist/services/remote-provisioner.d.ts +122 -0
  888. package/dist/services/remote-provisioner.d.ts.map +1 -0
  889. package/dist/services/remote-provisioner.js +258 -0
  890. package/dist/services/remote-provisioner.js.map +1 -0
  891. package/dist/services/secrets.rpc-service.d.ts +51 -2
  892. package/dist/services/secrets.rpc-service.d.ts.map +1 -1
  893. package/dist/services/secrets.rpc-service.js +81 -2
  894. package/dist/services/secrets.rpc-service.js.map +1 -1
  895. package/dist/services/secrets.service.d.ts +108 -9
  896. package/dist/services/secrets.service.d.ts.map +1 -1
  897. package/dist/services/secrets.service.js +313 -48
  898. package/dist/services/secrets.service.js.map +1 -1
  899. package/dist/services/slave-storage.service.d.ts +107 -0
  900. package/dist/services/slave-storage.service.d.ts.map +1 -1
  901. package/dist/services/slave-storage.service.js +171 -2
  902. package/dist/services/slave-storage.service.js.map +1 -1
  903. package/dist/services/static-carry-forward.d.ts +85 -0
  904. package/dist/services/static-carry-forward.d.ts.map +1 -0
  905. package/dist/services/static-carry-forward.js +159 -0
  906. package/dist/services/static-carry-forward.js.map +1 -0
  907. package/dist/services/sync-policy.d.ts +167 -0
  908. package/dist/services/sync-policy.d.ts.map +1 -0
  909. package/dist/services/sync-policy.js +161 -0
  910. package/dist/services/sync-policy.js.map +1 -0
  911. package/dist/services/sync-summary.d.ts +39 -0
  912. package/dist/services/sync-summary.d.ts.map +1 -0
  913. package/dist/services/sync-summary.js +62 -0
  914. package/dist/services/sync-summary.js.map +1 -0
  915. package/dist/services/sync.rpc-service.d.ts +19 -7
  916. package/dist/services/sync.rpc-service.d.ts.map +1 -1
  917. package/dist/services/sync.rpc-service.js +36 -5
  918. package/dist/services/sync.rpc-service.js.map +1 -1
  919. package/dist/services/sync.service.d.ts +350 -18
  920. package/dist/services/sync.service.d.ts.map +1 -1
  921. package/dist/services/sync.service.js +864 -116
  922. package/dist/services/sync.service.js.map +1 -1
  923. package/dist/services/system-info.rpc-service.d.ts +2 -1
  924. package/dist/services/system-info.rpc-service.d.ts.map +1 -1
  925. package/dist/services/system-info.rpc-service.js.map +1 -1
  926. package/dist/services/system-info.service.d.ts +56 -68
  927. package/dist/services/system-info.service.d.ts.map +1 -1
  928. package/dist/services/system-info.service.js +240 -127
  929. package/dist/services/system-info.service.js.map +1 -1
  930. package/dist/services/telemetry.rpc-service.d.ts.map +1 -1
  931. package/dist/services/telemetry.rpc-service.js +9 -3
  932. package/dist/services/telemetry.rpc-service.js.map +1 -1
  933. package/dist/services/telemetry.service.d.ts +4 -2
  934. package/dist/services/telemetry.service.d.ts.map +1 -1
  935. package/dist/services/telemetry.service.js +4 -2
  936. package/dist/services/telemetry.service.js.map +1 -1
  937. package/dist/services/trace-collector.rpc-service.d.ts +2 -1
  938. package/dist/services/trace-collector.rpc-service.d.ts.map +1 -1
  939. package/dist/services/trace-collector.rpc-service.js.map +1 -1
  940. package/dist/services/trace-collector.service.d.ts +2 -41
  941. package/dist/services/trace-collector.service.d.ts.map +1 -1
  942. package/dist/services/trace-collector.service.js +27 -7
  943. package/dist/services/trace-collector.service.js.map +1 -1
  944. package/dist/services/wait-for-postgres.d.ts +28 -0
  945. package/dist/services/wait-for-postgres.d.ts.map +1 -0
  946. package/dist/services/wait-for-postgres.js +77 -0
  947. package/dist/services/wait-for-postgres.js.map +1 -0
  948. package/dist/shared/alert-expression.d.ts +60 -0
  949. package/dist/shared/alert-expression.d.ts.map +1 -0
  950. package/dist/shared/alert-expression.js +124 -0
  951. package/dist/shared/alert-expression.js.map +1 -0
  952. package/dist/shared/audit-outcome.d.ts +39 -0
  953. package/dist/shared/audit-outcome.d.ts.map +1 -0
  954. package/dist/shared/audit-outcome.js +45 -0
  955. package/dist/shared/audit-outcome.js.map +1 -0
  956. package/dist/shared/build-freshness.d.ts +59 -0
  957. package/dist/shared/build-freshness.d.ts.map +1 -0
  958. package/dist/shared/build-freshness.js +113 -0
  959. package/dist/shared/build-freshness.js.map +1 -0
  960. package/dist/shared/build-stamp.d.ts +26 -0
  961. package/dist/shared/build-stamp.d.ts.map +1 -0
  962. package/dist/shared/build-stamp.js +36 -0
  963. package/dist/shared/build-stamp.js.map +1 -0
  964. package/dist/shared/describe-error.d.ts +22 -0
  965. package/dist/shared/describe-error.d.ts.map +1 -0
  966. package/dist/shared/describe-error.js +39 -0
  967. package/dist/shared/describe-error.js.map +1 -0
  968. package/dist/shared/dto/alerts.d.ts +101 -0
  969. package/dist/shared/dto/alerts.d.ts.map +1 -0
  970. package/dist/shared/dto/alerts.js +9 -0
  971. package/dist/shared/dto/alerts.js.map +1 -0
  972. package/dist/shared/dto/auth.d.ts +49 -0
  973. package/dist/shared/dto/auth.d.ts.map +1 -0
  974. package/dist/shared/dto/auth.js +14 -0
  975. package/dist/shared/dto/auth.js.map +1 -0
  976. package/dist/shared/dto/backups.d.ts +16 -0
  977. package/dist/shared/dto/backups.d.ts.map +1 -0
  978. package/dist/shared/dto/backups.js +9 -0
  979. package/dist/shared/dto/backups.js.map +1 -0
  980. package/dist/shared/dto/deploy.d.ts +28 -0
  981. package/dist/shared/dto/deploy.d.ts.map +1 -0
  982. package/dist/shared/dto/deploy.js +8 -0
  983. package/dist/shared/dto/deploy.js.map +1 -0
  984. package/dist/shared/dto/discovery.d.ts +24 -0
  985. package/dist/shared/dto/discovery.d.ts.map +1 -0
  986. package/dist/shared/dto/discovery.js +9 -0
  987. package/dist/shared/dto/discovery.js.map +1 -0
  988. package/dist/shared/dto/fleet.d.ts +35 -0
  989. package/dist/shared/dto/fleet.d.ts.map +1 -0
  990. package/dist/shared/dto/fleet.js +8 -0
  991. package/dist/shared/dto/fleet.js.map +1 -0
  992. package/dist/shared/dto/health.d.ts +26 -0
  993. package/dist/shared/dto/health.d.ts.map +1 -0
  994. package/dist/shared/dto/health.js +9 -0
  995. package/dist/shared/dto/health.js.map +1 -0
  996. package/dist/shared/dto/kubernetes.d.ts +44 -0
  997. package/dist/shared/dto/kubernetes.d.ts.map +1 -0
  998. package/dist/shared/dto/kubernetes.js +9 -0
  999. package/dist/shared/dto/kubernetes.js.map +1 -0
  1000. package/dist/shared/dto/logs.d.ts +77 -0
  1001. package/dist/shared/dto/logs.d.ts.map +1 -0
  1002. package/dist/shared/dto/logs.js +10 -0
  1003. package/dist/shared/dto/logs.js.map +1 -0
  1004. package/dist/shared/dto/metrics.d.ts +65 -0
  1005. package/dist/shared/dto/metrics.d.ts.map +1 -0
  1006. package/dist/shared/dto/metrics.js +17 -0
  1007. package/dist/shared/dto/metrics.js.map +1 -0
  1008. package/dist/shared/dto/nodes.d.ts +347 -0
  1009. package/dist/shared/dto/nodes.d.ts.map +1 -0
  1010. package/dist/shared/dto/nodes.js +8 -0
  1011. package/dist/shared/dto/nodes.js.map +1 -0
  1012. package/dist/shared/dto/pipelines.d.ts +53 -0
  1013. package/dist/shared/dto/pipelines.d.ts.map +1 -0
  1014. package/dist/shared/dto/pipelines.js +9 -0
  1015. package/dist/shared/dto/pipelines.js.map +1 -0
  1016. package/dist/shared/dto/project.d.ts +143 -9
  1017. package/dist/shared/dto/project.d.ts.map +1 -1
  1018. package/dist/shared/dto/services.d.ts +855 -7
  1019. package/dist/shared/dto/services.d.ts.map +1 -1
  1020. package/dist/shared/dto/system-info.d.ts +93 -0
  1021. package/dist/shared/dto/system-info.d.ts.map +1 -0
  1022. package/dist/shared/dto/system-info.js +9 -0
  1023. package/dist/shared/dto/system-info.js.map +1 -0
  1024. package/dist/shared/dto/traces.d.ts +49 -0
  1025. package/dist/shared/dto/traces.d.ts.map +1 -0
  1026. package/dist/shared/dto/traces.js +9 -0
  1027. package/dist/shared/dto/traces.js.map +1 -0
  1028. package/dist/shared/env-config.d.ts +74 -0
  1029. package/dist/shared/env-config.d.ts.map +1 -0
  1030. package/dist/shared/env-config.js +99 -0
  1031. package/dist/shared/env-config.js.map +1 -0
  1032. package/dist/shared/events.d.ts +45 -39
  1033. package/dist/shared/events.d.ts.map +1 -1
  1034. package/dist/shared/events.js +6 -0
  1035. package/dist/shared/events.js.map +1 -1
  1036. package/dist/shared/format.d.ts +1 -1
  1037. package/dist/shared/format.d.ts.map +1 -1
  1038. package/dist/shared/format.js +4 -0
  1039. package/dist/shared/format.js.map +1 -1
  1040. package/dist/shared/local-infra-host.d.ts +28 -0
  1041. package/dist/shared/local-infra-host.d.ts.map +1 -0
  1042. package/dist/shared/local-infra-host.js +28 -0
  1043. package/dist/shared/local-infra-host.js.map +1 -0
  1044. package/dist/shared/node-check.d.ts +37 -0
  1045. package/dist/shared/node-check.d.ts.map +1 -0
  1046. package/dist/shared/node-check.js +41 -0
  1047. package/dist/shared/node-check.js.map +1 -0
  1048. package/dist/shared/paths.d.ts +29 -0
  1049. package/dist/shared/paths.d.ts.map +1 -0
  1050. package/dist/shared/paths.js +54 -0
  1051. package/dist/shared/paths.js.map +1 -0
  1052. package/dist/shared/pnpm.d.ts +29 -0
  1053. package/dist/shared/pnpm.d.ts.map +1 -0
  1054. package/dist/shared/pnpm.js +57 -0
  1055. package/dist/shared/pnpm.js.map +1 -0
  1056. package/dist/shared/private-files.d.ts +29 -0
  1057. package/dist/shared/private-files.d.ts.map +1 -0
  1058. package/dist/shared/private-files.js +109 -0
  1059. package/dist/shared/private-files.js.map +1 -0
  1060. package/dist/shared/redact-env.d.ts +24 -0
  1061. package/dist/shared/redact-env.d.ts.map +1 -0
  1062. package/dist/shared/redact-env.js +36 -0
  1063. package/dist/shared/redact-env.js.map +1 -0
  1064. package/dist/shared/release-reading.d.ts +85 -0
  1065. package/dist/shared/release-reading.d.ts.map +1 -0
  1066. package/dist/shared/release-reading.js +81 -0
  1067. package/dist/shared/release-reading.js.map +1 -0
  1068. package/dist/shared/roles.d.ts +58 -3
  1069. package/dist/shared/roles.d.ts.map +1 -1
  1070. package/dist/shared/roles.js +55 -0
  1071. package/dist/shared/roles.js.map +1 -1
  1072. package/dist/shared/rpcauth.d.ts +13 -0
  1073. package/dist/shared/rpcauth.d.ts.map +1 -0
  1074. package/dist/shared/rpcauth.js +23 -0
  1075. package/dist/shared/rpcauth.js.map +1 -0
  1076. package/dist/shared/shell-escape.d.ts +9 -0
  1077. package/dist/shared/shell-escape.d.ts.map +1 -0
  1078. package/dist/shared/shell-escape.js +11 -0
  1079. package/dist/shared/shell-escape.js.map +1 -0
  1080. package/dist/shared/sync-reading.d.ts +45 -0
  1081. package/dist/shared/sync-reading.d.ts.map +1 -0
  1082. package/dist/shared/sync-reading.js +42 -0
  1083. package/dist/shared/sync-reading.js.map +1 -0
  1084. package/dist/shared/tokens.d.ts +19 -0
  1085. package/dist/shared/tokens.d.ts.map +1 -1
  1086. package/dist/shared/tokens.js +28 -0
  1087. package/dist/shared/tokens.js.map +1 -1
  1088. package/dist/webapp/webapp.service.d.ts +33 -2
  1089. package/dist/webapp/webapp.service.d.ts.map +1 -1
  1090. package/dist/webapp/webapp.service.js +143 -31
  1091. package/dist/webapp/webapp.service.js.map +1 -1
  1092. package/dist/workers/health-monitor-process.d.ts.map +1 -1
  1093. package/dist/workers/health-monitor-process.js +10 -0
  1094. package/dist/workers/health-monitor-process.js.map +1 -1
  1095. package/dist/workers/health-monitor.service.d.ts +45 -3
  1096. package/dist/workers/health-monitor.service.d.ts.map +1 -1
  1097. package/dist/workers/health-monitor.service.js +156 -26
  1098. package/dist/workers/health-monitor.service.js.map +1 -1
  1099. package/dist/workers/system-worker-manager.d.ts +43 -0
  1100. package/dist/workers/system-worker-manager.d.ts.map +1 -1
  1101. package/dist/workers/system-worker-manager.js +150 -3
  1102. package/dist/workers/system-worker-manager.js.map +1 -1
  1103. package/dist/workers/types.d.ts +11 -2
  1104. package/dist/workers/types.d.ts.map +1 -1
  1105. package/package.json +64 -29
  1106. package/webapp/dist/BUILD.json +5 -0
  1107. package/webapp/dist/assets/FormControlLabel-BrH2diyl.js +1 -0
  1108. package/webapp/dist/assets/Grid-BZ7xhoHQ.js +1 -0
  1109. package/webapp/dist/assets/Switch-DGSAxQPM.js +1 -0
  1110. package/webapp/dist/assets/alerts-sXqHJbsa.js +1 -0
  1111. package/webapp/dist/assets/apps-B_Ah8Flh.js +1 -0
  1112. package/webapp/dist/assets/audit-YXihwyui.js +1 -0
  1113. package/webapp/dist/assets/client-CGbBvy9k.js +1 -0
  1114. package/webapp/dist/assets/constants-veKGFkC6.js +1 -0
  1115. package/webapp/dist/assets/containers-Di4NOTLf.js +2 -0
  1116. package/webapp/dist/assets/daemon-memory-CCPZ4cV_.js +1 -0
  1117. package/webapp/dist/assets/dashboard-Cfuf95N3.js +1 -0
  1118. package/webapp/dist/assets/dashboard-builder-CowaYb-M.js +1 -0
  1119. package/webapp/dist/assets/deploy-release-dialog-D6C-XcKY.js +1 -0
  1120. package/webapp/dist/assets/deployments-ChTq5kCw.js +1 -0
  1121. package/webapp/dist/assets/detail-BsGWv7Dj.js +1 -0
  1122. package/webapp/dist/assets/detail-CyVf_cw5.js +2 -0
  1123. package/webapp/dist/assets/detail-D027j6aO.js +8 -0
  1124. package/webapp/dist/assets/formatters-BqjL73N3.js +1 -0
  1125. package/webapp/dist/assets/index-B8AHIPc-.css +1 -0
  1126. package/webapp/dist/assets/index-DiZbrwxT.js +414 -0
  1127. package/webapp/dist/assets/logs-L2b8Oqmo.js +12 -0
  1128. package/webapp/dist/assets/maplibre-gl-MlmG2kbn.js +801 -0
  1129. package/webapp/dist/assets/metrics-CQgjz2Lz.js +2 -0
  1130. package/webapp/dist/assets/nodes-Nwia2Ty6.js +7 -0
  1131. package/webapp/dist/assets/pipelines-DCu_rXOr.js +4 -0
  1132. package/webapp/dist/assets/projects-Bb4aV76h.js +1 -0
  1133. package/webapp/dist/assets/react-CwJFpaho.js +1 -0
  1134. package/webapp/dist/assets/react-apexcharts.esm-Dy0Fez42.js +1956 -0
  1135. package/webapp/dist/assets/release-bits-Dj4EOhhb.js +1 -0
  1136. package/webapp/dist/assets/release-build-panel-D6OCVlhT.js +1 -0
  1137. package/webapp/dist/assets/releases-CnAt3yO6.js +2 -0
  1138. package/webapp/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
  1139. package/webapp/dist/assets/settings-DU-mjiwb.js +1 -0
  1140. package/webapp/dist/assets/settled-pair-C7SjZuns.js +1 -0
  1141. package/webapp/dist/assets/sign-in-Bcvjrr4C.js +1 -0
  1142. package/webapp/dist/assets/stacks-B-e8p50I.js +1 -0
  1143. package/webapp/dist/assets/sync-reading-C3PnJ7AX.js +1 -0
  1144. package/webapp/dist/assets/system-info-BtE3dgfw.js +1 -0
  1145. package/webapp/dist/assets/topology-Cwch-uF1.js +12 -0
  1146. package/webapp/dist/assets/topology-DLioOiRN.css +1 -0
  1147. package/webapp/dist/assets/traces-BbShR-4P.js +1 -0
  1148. package/webapp/dist/assets/use-stack-context-CZUgPq88.js +1 -0
  1149. package/webapp/dist/index.html +6 -7
  1150. package/dist/commands/dev.d.ts +0 -23
  1151. package/dist/commands/dev.d.ts.map +0 -1
  1152. package/dist/commands/dev.js +0 -76
  1153. package/dist/commands/dev.js.map +0 -1
  1154. package/dist/config/define-app.d.ts +0 -6
  1155. package/dist/config/define-app.d.ts.map +0 -1
  1156. package/dist/config/define-app.js +0 -38
  1157. package/dist/config/define-app.js.map +0 -1
  1158. package/dist/infrastructure/gateway-generator.d.ts +0 -63
  1159. package/dist/infrastructure/gateway-generator.d.ts.map +0 -1
  1160. package/dist/infrastructure/gateway-generator.js +0 -253
  1161. package/dist/infrastructure/gateway-generator.js.map +0 -1
  1162. package/dist/monitoring/health.service.d.ts +0 -14
  1163. package/dist/monitoring/health.service.d.ts.map +0 -1
  1164. package/dist/monitoring/health.service.js +0 -50
  1165. package/dist/monitoring/health.service.js.map +0 -1
  1166. package/dist/monitoring/metrics.service.d.ts +0 -14
  1167. package/dist/monitoring/metrics.service.d.ts.map +0 -1
  1168. package/dist/monitoring/metrics.service.js +0 -40
  1169. package/dist/monitoring/metrics.service.js.map +0 -1
  1170. package/dist/orchestrator/bootstrap-runner.d.ts +0 -15
  1171. package/dist/orchestrator/bootstrap-runner.d.ts.map +0 -1
  1172. package/dist/orchestrator/bootstrap-runner.js +0 -152
  1173. package/dist/orchestrator/bootstrap-runner.js.map +0 -1
  1174. package/dist/orchestrator/topology-proxy.d.ts +0 -65
  1175. package/dist/orchestrator/topology-proxy.d.ts.map +0 -1
  1176. package/dist/orchestrator/topology-proxy.js +0 -209
  1177. package/dist/orchestrator/topology-proxy.js.map +0 -1
  1178. package/dist/orchestrator/topology-relay.d.ts +0 -111
  1179. package/dist/orchestrator/topology-relay.d.ts.map +0 -1
  1180. package/dist/orchestrator/topology-relay.js +0 -255
  1181. package/dist/orchestrator/topology-relay.js.map +0 -1
  1182. package/dist/services/auth-middleware.d.ts +0 -47
  1183. package/dist/services/auth-middleware.d.ts.map +0 -1
  1184. package/dist/services/auth-middleware.js +0 -158
  1185. package/dist/services/auth-middleware.js.map +0 -1
  1186. package/dist/services/environment.rpc-service.d.ts +0 -22
  1187. package/dist/services/environment.rpc-service.d.ts.map +0 -1
  1188. package/dist/services/environment.rpc-service.js +0 -65
  1189. package/dist/services/environment.rpc-service.js.map +0 -1
  1190. package/dist/services/environment.service.d.ts +0 -87
  1191. package/dist/services/environment.service.d.ts.map +0 -1
  1192. package/dist/services/environment.service.js +0 -220
  1193. package/dist/services/environment.service.js.map +0 -1
  1194. package/dist/services/metrics-collector.service.d.ts +0 -103
  1195. package/dist/services/metrics-collector.service.d.ts.map +0 -1
  1196. package/dist/services/metrics-collector.service.js +0 -235
  1197. package/dist/services/metrics-collector.service.js.map +0 -1
  1198. package/dist/services/metrics.rpc-service.d.ts +0 -41
  1199. package/dist/services/metrics.rpc-service.d.ts.map +0 -1
  1200. package/dist/services/metrics.rpc-service.js +0 -90
  1201. package/dist/services/metrics.rpc-service.js.map +0 -1
  1202. package/dist/services/metrics.service.d.ts +0 -72
  1203. package/dist/services/metrics.service.d.ts.map +0 -1
  1204. package/dist/services/metrics.service.js +0 -185
  1205. package/dist/services/metrics.service.js.map +0 -1
  1206. package/dist/supervisor/omnitron-supervisor.d.ts +0 -21
  1207. package/dist/supervisor/omnitron-supervisor.d.ts.map +0 -1
  1208. package/dist/supervisor/omnitron-supervisor.js +0 -43
  1209. package/dist/supervisor/omnitron-supervisor.js.map +0 -1
  1210. package/dist/webapp/static-server.d.ts +0 -24
  1211. package/dist/webapp/static-server.d.ts.map +0 -1
  1212. package/dist/webapp/static-server.js +0 -152
  1213. package/dist/webapp/static-server.js.map +0 -1
  1214. package/webapp/dist/assets/Chip-BySxTjyN.js +0 -1
  1215. package/webapp/dist/assets/DialogContentText-YQWiAVrU.js +0 -1
  1216. package/webapp/dist/assets/DialogTitle-CDkgUIwp.js +0 -1
  1217. package/webapp/dist/assets/FormControlLabel-Bu3CCsBM.js +0 -1
  1218. package/webapp/dist/assets/Grid-BFY8hAzL.js +0 -1
  1219. package/webapp/dist/assets/InputAdornment-_Dayk-3y.js +0 -3
  1220. package/webapp/dist/assets/Skeleton-BGj6Sw8m.js +0 -37
  1221. package/webapp/dist/assets/Switch-CA6682vv.js +0 -1
  1222. package/webapp/dist/assets/TableContainer-4epq10KJ.js +0 -1
  1223. package/webapp/dist/assets/TextField-C73KHMVN.js +0 -1
  1224. package/webapp/dist/assets/alerts-JEQALS7Y.js +0 -1
  1225. package/webapp/dist/assets/apps-DMPysEKB.js +0 -1
  1226. package/webapp/dist/assets/client-DlGPter5.js +0 -110
  1227. package/webapp/dist/assets/constants-DqFQJ27U.js +0 -1
  1228. package/webapp/dist/assets/containers-CvkC7do8.js +0 -1
  1229. package/webapp/dist/assets/dashboard-C0Fre9pC.js +0 -1
  1230. package/webapp/dist/assets/dashboard-builder-DAghqdpE.js +0 -1
  1231. package/webapp/dist/assets/deployments-Cg1lI1uT.js +0 -1
  1232. package/webapp/dist/assets/detail-CyFtEson.js +0 -1
  1233. package/webapp/dist/assets/detail-DqoSGKT1.js +0 -8
  1234. package/webapp/dist/assets/formatters-J3Xqn6BQ.js +0 -1
  1235. package/webapp/dist/assets/icons-ynIWYfBP.js +0 -3
  1236. package/webapp/dist/assets/index-CHVXOsTS.css +0 -1
  1237. package/webapp/dist/assets/index-vKrDmEA_.js +0 -259
  1238. package/webapp/dist/assets/isMuiElement-BRL3YuCT.js +0 -1
  1239. package/webapp/dist/assets/logs-IovIij1C.js +0 -11
  1240. package/webapp/dist/assets/metrics-Dufwtwjq.js +0 -1
  1241. package/webapp/dist/assets/nodes-Brvu8W3j.js +0 -7
  1242. package/webapp/dist/assets/pipelines-t40X4MuC.js +0 -4
  1243. package/webapp/dist/assets/prop-types-CvVtHxp4.js +0 -1
  1244. package/webapp/dist/assets/react-apexcharts.esm-CLO6gala.js +0 -954
  1245. package/webapp/dist/assets/settings-DTAIST3v.js +0 -1
  1246. package/webapp/dist/assets/sign-in-DQEAkJum.js +0 -1
  1247. package/webapp/dist/assets/stacks-BjM1f45N.js +0 -1
  1248. package/webapp/dist/assets/system-info-BQSbSEK-.js +0 -1
  1249. package/webapp/dist/assets/topology-6N8-Az_Z.js +0 -12
  1250. package/webapp/dist/assets/topology-CHpVij2M.css +0 -1
  1251. package/webapp/dist/assets/traces-DVXyb-4m.js +0 -1
  1252. package/webapp/dist/assets/use-stack-context-CbE8fxBA.js +0 -1
  1253. /package/webapp/dist/assets/{fs-uP8eiZAR.js → fs-Ccl3sAcp.js} +0 -0
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * NodeManagerService — Manages infrastructure nodes (machines)
3
3
  *
4
- * File-based storage at ~/.omnitron/nodes.json (no PG dependency).
4
+ * Registry lives in the SQLite-backed `nodes` table of DaemonStateStore.
5
+ * `~/.omnitron/nodes.json` is read once, on a boot that finds the table
6
+ * empty, and then unlinked — the header claimed the JSON file was still the
7
+ * storage long after T-7 moved it, which is the kind of thing a reader
8
+ * believes because there is nothing to contradict it.
5
9
  * Always includes a "local" node for the local machine.
6
10
  * Remote nodes are accessed via SSH for provisioning and management.
7
11
  */
@@ -10,53 +14,213 @@ import path from 'node:path';
10
14
  import os from 'node:os';
11
15
  import { EventEmitter } from 'node:events';
12
16
  import { randomUUID } from 'node:crypto';
13
- import { RemoteOpsService, DEFAULT_CHECK_CONFIG } from './remote-ops.service.js';
17
+ import { RemoteOpsService, DEFAULT_CHECK_CONFIG, normalizeCheckConfig, assertNodeHost, } from './remote-ops.service.js';
18
+ import { CLI_VERSION } from '../config/defaults.js';
14
19
  // =============================================================================
15
20
  // Constants
16
21
  // =============================================================================
17
22
  const OMNITRON_HOME = path.join(os.homedir(), '.omnitron');
18
23
  const NODES_FILE = path.join(OMNITRON_HOME, 'nodes.json');
19
24
  const LOCAL_NODE_ID = 'local';
25
+ /** DaemonStateStore key holding the operator-set check configuration. */
26
+ const CHECK_CONFIG_KEY = 'nodes:check-config';
20
27
  // =============================================================================
21
28
  // Service
22
29
  // =============================================================================
23
30
  export class NodeManagerService extends EventEmitter {
24
31
  logger;
32
+ store;
25
33
  secrets;
26
34
  nodes = new Map();
27
35
  statusCache = new Map();
36
+ /**
37
+ * Aggregated health per node — the shape the worker reports and the console
38
+ * reads. Kept here so a daemon whose worker is down can still answer
39
+ * `triggerNodeCheck`, and so status TRANSITIONS have something to compare
40
+ * against: `node.went_offline` and its siblings are declared event channels
41
+ * that nothing ever emitted, because no one held the previous value.
42
+ */
43
+ summaryCache = new Map();
28
44
  remoteOps;
29
45
  checkConfig = DEFAULT_CHECK_CONFIG;
30
- constructor(logger, secrets) {
46
+ /** Set by the daemon from its own config; see `setHistoryConfig`. */
47
+ historyConfig = { uptimeIntervalMs: 86_400_000, retentionDays: 90 };
48
+ /**
49
+ * Secrets read out of a node row and not yet written to the vault.
50
+ *
51
+ * The migration in `healLeakedSecrets` is async and starts at construction;
52
+ * without this, a check running in that window would find no passphrase and
53
+ * report a perfectly reachable node as unreachable.
54
+ */
55
+ pendingSecrets = new Map();
56
+ /** The master's mesh — see `setSlaveConnector`. */
57
+ mesh = null;
58
+ constructor(logger,
59
+ /**
60
+ * T-7 — fleet node registry persistence moved off
61
+ * ~/.omnitron/nodes.json onto the SQLite-backed `nodes` table
62
+ * in DaemonStateStore.
63
+ * Canonical name/host/port are denormalised into typed columns
64
+ * for queries; the full INode payload (SSH config, tags, etc.)
65
+ * lives in the `metadata` column as JSON.
66
+ */
67
+ store, secrets) {
31
68
  super();
32
69
  this.logger = logger;
70
+ this.store = store;
33
71
  this.secrets = secrets;
34
72
  this.remoteOps = new RemoteOpsService(logger);
35
73
  this.load();
36
74
  this.ensureLocalNode();
37
- this.initLocalStatus();
38
75
  }
39
- /** Update check configuration (ping/SSH timeouts, ping enabled/disabled) */
76
+ /**
77
+ * Update check configuration (ping/SSH timeouts, ping enabled/disabled).
78
+ *
79
+ * Persisted and announced. Both were missing: the setting lived in this
80
+ * field alone, so it was lost on restart, and the health-monitor worker —
81
+ * which performs every check the console displays — kept running with the
82
+ * values it was handed at boot. An operator turning ping off in the console
83
+ * changed a value that only the daemon's own fallback path ever read.
84
+ */
40
85
  setCheckConfig(config) {
41
- this.checkConfig = { ...this.checkConfig, ...config };
86
+ const next = normalizeCheckConfig({ ...this.checkConfig, ...config });
87
+ const changed = Object.keys(next)
88
+ .some((k) => next[k] !== this.checkConfig[k]);
89
+ this.checkConfig = next;
90
+ if (!changed)
91
+ return;
92
+ try {
93
+ this.store.kvSetSync(CHECK_CONFIG_KEY, next);
94
+ }
95
+ catch (err) {
96
+ this.logger.warn({ error: err.message }, 'Failed to persist node check config');
97
+ }
98
+ this.logger.info({ config: next }, 'Node check config updated');
99
+ this.emit('checkConfig:changed', next);
42
100
  }
43
101
  getCheckConfig() {
44
102
  return { ...this.checkConfig };
45
103
  }
104
+ /**
105
+ * Tell the service how history is kept, so the console can be told too.
106
+ *
107
+ * `uptimeIntervalMs` was declared in the daemon config, documented, given a
108
+ * default — and read by nothing. The console used a constant of its own,
109
+ * and no caller anywhere could have discovered the retention window that
110
+ * bounds what the bars can show.
111
+ */
112
+ setHistoryConfig(config) {
113
+ if (Number.isFinite(config.uptimeIntervalMs)) {
114
+ this.historyConfig.uptimeIntervalMs = config.uptimeIntervalMs;
115
+ }
116
+ if (Number.isFinite(config.retentionDays)) {
117
+ this.historyConfig.retentionDays = config.retentionDays;
118
+ }
119
+ }
120
+ getHistoryConfig() {
121
+ return { ...this.historyConfig };
122
+ }
123
+ /**
124
+ * The master's mesh, so a check asks a node's daemon over the connection
125
+ * the master already holds to it.
126
+ *
127
+ * Without it this service could only dial `tcp://<host>:<daemonPort>`, and
128
+ * a hardened node's daemon port is closed to the master — that is why the
129
+ * mesh tunnels over SSH. Measured 2026-09-23 with the health worker
130
+ * detached: `omnitron node check` on daos-test printed `Omnitron: ○
131
+ * offline` / `Connection timeout to tcp://37.27.130.185:9700` while the
132
+ * mesh held that node `connected via ssh-tunnel, authenticated` and
133
+ * `fleet status` read six apps from it through that connection. The
134
+ * comment above the probe said the SlaveConnector was asked first; the
135
+ * code never asked it.
136
+ */
137
+ setSlaveConnector(connector) {
138
+ this.mesh = connector;
139
+ }
46
140
  // ===========================================================================
47
141
  // CRUD
48
142
  // ===========================================================================
49
143
  listNodes() {
50
144
  return Array.from(this.nodes.values()).map((node) => ({
51
- ...node,
52
- status: this.statusCache.get(node.id) ?? null,
145
+ ...toWireNode(node),
146
+ status: this.statusFor(node.id),
53
147
  }));
54
148
  }
55
149
  getNode(id) {
56
150
  const node = this.nodes.get(id);
57
151
  if (!node)
58
152
  return null;
59
- return { ...node, status: this.statusCache.get(id) ?? null };
153
+ return { ...toWireNode(node), status: this.statusFor(id) };
154
+ }
155
+ /**
156
+ * Status for one node.
157
+ *
158
+ * For the local node the facts about this daemon — version, pid, uptime,
159
+ * role — are read from `process` on every call. They used to be written
160
+ * once into the cache in the constructor, so `omnitronUptime` was whatever
161
+ * `process.uptime()` returned a few milliseconds into boot, and the
162
+ * console renders that as "Uptime": a handful of seconds, however long the
163
+ * daemon had been up.
164
+ *
165
+ * The health-monitor worker also checks the local node, and what it
166
+ * reports is not worthless — whether sshd answers on loopback is a real
167
+ * check, and it is the only source for `checkedAt`, which dates the
168
+ * reachability reading rather than this call. So the worker's status is
169
+ * kept and only the fields the daemon knows first-hand are overwritten.
170
+ * Neither source is discarded, because neither one is redundant.
171
+ */
172
+ statusFor(id) {
173
+ if (id !== LOCAL_NODE_ID)
174
+ return this.statusCache.get(id) ?? null;
175
+ const live = this.localStatus();
176
+ const checked = this.statusCache.get(LOCAL_NODE_ID);
177
+ if (!checked)
178
+ return live;
179
+ const merged = { ...checked, omnitronConnected: true };
180
+ // Assigned rather than spread: the fields are optional under
181
+ // `exactOptionalPropertyTypes`, so writing `undefined` into them is a
182
+ // different thing from leaving them out.
183
+ if (live.omnitronVersion !== undefined)
184
+ merged.omnitronVersion = live.omnitronVersion;
185
+ if (live.omnitronPid !== undefined)
186
+ merged.omnitronPid = live.omnitronPid;
187
+ if (live.omnitronUptime !== undefined)
188
+ merged.omnitronUptime = live.omnitronUptime;
189
+ if (live.omnitronRole !== undefined)
190
+ merged.omnitronRole = live.omnitronRole;
191
+ return merged;
192
+ }
193
+ /**
194
+ * One row per daemon.
195
+ *
196
+ * `host` plus `daemonPort` names a DAEMON, and two registry rows naming
197
+ * the same one are always a mistake — there is no second thing there to
198
+ * manage. Two daemons on one machine are two ports, and those are still
199
+ * allowed.
200
+ *
201
+ * It was worth every cost it caused, all measured on one machine that had
202
+ * been registered twice:
203
+ *
204
+ * - the health monitor checked it on both rows, 120 connections an hour
205
+ * to one socket;
206
+ * - `fleet upgrade` transferred and installed the bundle to it twice;
207
+ * - the mesh holds one connection per ADDRESS, so exactly one of the two
208
+ * rows receives the node's data and the other reads "not joined"
209
+ * forever — and which one is arbitrary.
210
+ *
211
+ * Refused rather than merged: the existing row may carry credentials,
212
+ * tags and history, and picking which of two to keep is the operator's
213
+ * call, not this function's.
214
+ */
215
+ assertAddressIsFree(host, daemonPort, exceptId) {
216
+ for (const existing of this.nodes.values()) {
217
+ if (existing.id === exceptId)
218
+ continue;
219
+ if (existing.host !== host || existing.daemonPort !== daemonPort)
220
+ continue;
221
+ throw new Error(`${host}:${daemonPort} is already registered as "${existing.name}". ` +
222
+ 'One row per daemon — edit that node, or give this one a different daemon port.');
223
+ }
60
224
  }
61
225
  async addNode(input) {
62
226
  const id = randomUUID();
@@ -64,19 +228,25 @@ export class NodeManagerService extends EventEmitter {
64
228
  const node = {
65
229
  id,
66
230
  name: input.name,
67
- host: input.host,
68
- sshPort: input.sshPort ?? 22,
231
+ // A host is not free text: it is spelled into an SSH target and into
232
+ // the argument list of `ping`. Rejected at the WRITE so a stored value
233
+ // cannot surprise a reader downstream.
234
+ host: assertNodeHost(input.host),
235
+ sshPort: assertPort('SSH port', input.sshPort ?? 22),
69
236
  sshUser: input.sshUser ?? 'root',
70
237
  sshAuthMethod: input.sshAuthMethod ?? 'key',
71
238
  ...(input.sshPrivateKey && { sshPrivateKey: input.sshPrivateKey }),
72
239
  runtime: input.runtime ?? 'node',
73
- daemonPort: input.daemonPort ?? 9700,
240
+ daemonPort: assertPort('daemon port', input.daemonPort ?? 9700),
74
241
  tags: input.tags ?? [],
75
242
  isLocal: false,
76
243
  createdAt: now,
77
244
  updatedAt: now,
78
245
  ...(input.offlineTimeout != null && { offlineTimeout: input.offlineTimeout }),
79
246
  };
247
+ if (!node.name.trim())
248
+ throw new Error('Node name is required');
249
+ this.assertAddressIsFree(node.host, node.daemonPort);
80
250
  // Store secrets encrypted (passphrase, password) — only boolean markers in nodes.json.
81
251
  // Must await before connectivity check, otherwise getSecret() reads stale file.
82
252
  if (input.sshPassphrase) {
@@ -91,8 +261,14 @@ export class NodeManagerService extends EventEmitter {
91
261
  this.save();
92
262
  this.emit('node:added', node);
93
263
  this.logger.info({ nodeId: id, name: node.name, host: node.host }, 'Node added');
94
- // Check connectivity in background — secrets are already persisted
95
- void this.checkNodeStatus(id).catch(() => { });
264
+ // Check connectivity in background — secrets are already persisted.
265
+ // `checkNodeStatus` records an unreachable host in the status it returns
266
+ // rather than throwing, so anything arriving here is a fault in the probe
267
+ // itself, and swallowing it leaves the node "unchecked" for ever with
268
+ // nothing to explain why.
269
+ void this.checkNodeStatus(id).catch((err) => {
270
+ this.logger.warn({ nodeId: id, err }, 'Connectivity check failed to run');
271
+ });
96
272
  return node;
97
273
  }
98
274
  async updateNode(id, input) {
@@ -103,6 +279,12 @@ export class NodeManagerService extends EventEmitter {
103
279
  throw new Error('Cannot change host of local node');
104
280
  // Extract secrets before spreading into node (they must not be saved to nodes.json)
105
281
  const { sshPassphrase, sshPassword, ...safeInput } = input;
282
+ if (safeInput.host !== undefined)
283
+ safeInput.host = assertNodeHost(safeInput.host);
284
+ if (safeInput.sshPort !== undefined)
285
+ safeInput.sshPort = assertPort('SSH port', safeInput.sshPort);
286
+ if (safeInput.daemonPort !== undefined)
287
+ safeInput.daemonPort = assertPort('daemon port', safeInput.daemonPort);
106
288
  const updated = {
107
289
  ...node,
108
290
  ...safeInput,
@@ -111,6 +293,25 @@ export class NodeManagerService extends EventEmitter {
111
293
  createdAt: node.createdAt,
112
294
  updatedAt: new Date().toISOString(),
113
295
  };
296
+ // An edit can collide as readily as an add — correcting one node's host
297
+ // to the address another already holds is exactly how a duplicate gets
298
+ // made. Checked before any secret is written, so a refused edit leaves
299
+ // nothing behind.
300
+ //
301
+ // Only when the edit MOVES the row. A registry that already holds two
302
+ // rows for one daemon — made before this rule existed — refused every
303
+ // edit to either of them, including the one that would have repaired it:
304
+ //
305
+ // omnitron node update <id> --ssh-auth password
306
+ // 37.27.130.185:9700 is already registered as "acme-deploy-test"
307
+ //
308
+ // The guard exists to stop a duplicate being CREATED. Refusing an edit
309
+ // that changes neither the host nor the port cannot prevent one, and it
310
+ // leaves an operator with a registry they can neither use nor mend.
311
+ const addressChanged = updated.host !== node.host || updated.daemonPort !== node.daemonPort;
312
+ if (addressChanged) {
313
+ this.assertAddressIsFree(updated.host, updated.daemonPort, id);
314
+ }
114
315
  // Update encrypted secrets — await to ensure they're persisted before connectivity check
115
316
  if (sshPassphrase !== undefined) {
116
317
  if (sshPassphrase) {
@@ -132,26 +333,66 @@ export class NodeManagerService extends EventEmitter {
132
333
  await this.deleteSecret(id, 'password');
133
334
  }
134
335
  }
336
+ // A credential that belongs to the other auth method is dead weight that
337
+ // still authenticates: leaving a stored password on a node switched to
338
+ // key auth means the console shows "SSH Key" while the daemon may log in
339
+ // with a password the operator believes they stopped using.
340
+ if (updated.sshAuthMethod !== node.sshAuthMethod) {
341
+ if (updated.sshAuthMethod === 'key' && updated.hasPassword) {
342
+ updated.hasPassword = false;
343
+ await this.deleteSecret(id, 'password');
344
+ }
345
+ if (updated.sshAuthMethod === 'password') {
346
+ delete updated.sshPrivateKey;
347
+ if (updated.hasPassphrase) {
348
+ updated.hasPassphrase = false;
349
+ await this.deleteSecret(id, 'passphrase');
350
+ }
351
+ }
352
+ }
135
353
  this.nodes.set(id, updated);
136
354
  this.save();
137
355
  this.emit('node:updated', updated);
138
356
  // Re-check connectivity after update
139
357
  if (!updated.isLocal) {
140
- void this.checkNodeStatus(id).catch(() => { });
358
+ void this.checkNodeStatus(id).catch((err) => {
359
+ this.logger.warn({ nodeId: id, err }, 'Connectivity check failed to run');
360
+ });
141
361
  }
142
362
  return updated;
143
363
  }
144
- removeNode(id) {
364
+ /**
365
+ * Remove a node from the registry.
366
+ *
367
+ * Deletes the ROW, not just the map entry. `save()` rewrites every node
368
+ * still held in memory, which is how the file-backed registry used to
369
+ * express a deletion — but an UPSERT-per-row store expresses it by
370
+ * deleting, and the row for a removed node stayed behind. The console
371
+ * reported the node gone, and the next daemon start read it back in.
372
+ *
373
+ * Secret deletion is awaited for the same reason: fired and forgotten, a
374
+ * failure left an SSH password in the vault under the id of a node nobody
375
+ * can see any more.
376
+ */
377
+ async removeNode(id) {
145
378
  const node = this.nodes.get(id);
146
379
  if (!node)
147
380
  throw new Error(`Node not found: ${id}`);
148
381
  if (node.isLocal)
149
382
  throw new Error('Cannot remove local node');
150
383
  // Clean up encrypted secrets
151
- void this.deleteSecret(id, 'passphrase');
152
- void this.deleteSecret(id, 'password');
384
+ await this.deleteSecret(id, 'passphrase');
385
+ await this.deleteSecret(id, 'password');
153
386
  this.nodes.delete(id);
154
387
  this.statusCache.delete(id);
388
+ this.summaryCache.delete(id);
389
+ try {
390
+ this.store.deleteNodeSync(id);
391
+ }
392
+ catch (err) {
393
+ this.logger.warn({ nodeId: id, error: err.message }, 'Failed to delete node row');
394
+ throw err;
395
+ }
155
396
  this.save();
156
397
  this.emit('node:removed', id);
157
398
  this.logger.info({ nodeId: id, name: node.name }, 'Node removed');
@@ -185,25 +426,29 @@ export class NodeManagerService extends EventEmitter {
185
426
  entry === 'authorized_keys') {
186
427
  continue;
187
428
  }
188
- // Check if it looks like a private key (starts with -----BEGIN)
429
+ // Check if it looks like a private key (starts with -----BEGIN).
430
+ // Read the HEADER, not the file: this walks a directory of private
431
+ // keys, and `readFileSync(...).slice(0, 100)` pulled every byte of
432
+ // every one of them into the daemon's heap to look at the first line.
433
+ let head;
189
434
  try {
190
- const head = fs.readFileSync(fullPath, 'utf-8').slice(0, 100);
191
- if (head.includes('-----BEGIN') && head.includes('KEY')) {
192
- // Detect key type from header
193
- let type = 'unknown';
194
- if (head.includes('RSA'))
195
- type = 'rsa';
196
- else if (head.includes('EC'))
197
- type = 'ecdsa';
198
- else if (head.includes('OPENSSH'))
199
- type = 'ed25519';
200
- else if (head.includes('DSA'))
201
- type = 'dsa';
202
- keys.push({ name: entry, path: fullPath, type });
203
- }
435
+ head = readFileHead(fullPath, 100);
204
436
  }
205
437
  catch {
206
- // Can't read — skip
438
+ continue; // Can't read — skip
439
+ }
440
+ if (head.includes('-----BEGIN') && head.includes('KEY')) {
441
+ // Detect key type from header
442
+ let type = 'unknown';
443
+ if (head.includes('RSA'))
444
+ type = 'rsa';
445
+ else if (head.includes('EC'))
446
+ type = 'ecdsa';
447
+ else if (head.includes('OPENSSH'))
448
+ type = 'ed25519';
449
+ else if (head.includes('DSA'))
450
+ type = 'dsa';
451
+ keys.push({ name: entry, path: fullPath, type });
207
452
  }
208
453
  }
209
454
  return keys;
@@ -219,7 +464,9 @@ export class NodeManagerService extends EventEmitter {
219
464
  nodeId: id,
220
465
  pingReachable: false,
221
466
  pingLatencyMs: null,
222
- sshConnected: false,
467
+ // Not `false`: this check does not open an SSH session at all, and
468
+ // `false` reads as "SSH was refused" everywhere it is consumed.
469
+ sshConnected: null,
223
470
  sshLatencyMs: null,
224
471
  omnitronConnected: false,
225
472
  checkedAt: new Date().toISOString(),
@@ -234,22 +481,18 @@ export class NodeManagerService extends EventEmitter {
234
481
  status.omnitronPid = process.pid;
235
482
  status.omnitronUptime = process.uptime() * 1000;
236
483
  status.omnitronRole = 'master';
484
+ status.omnitronVersion = CLI_VERSION;
237
485
  status.os = {
238
486
  platform: os.platform(),
239
487
  arch: os.arch(),
240
488
  hostname: os.hostname(),
241
489
  release: os.release(),
242
490
  };
243
- try {
244
- const { CLI_VERSION } = await import('../config/defaults.js');
245
- status.omnitronVersion = CLI_VERSION;
246
- }
247
- catch {
248
- status.omnitronVersion = '0.1.0';
249
- }
250
491
  }
251
492
  else {
252
- // Remote node — ping + Netron TCP (no SSH — SSH is manual-only via UI)
493
+ // Remote node — ping, then the daemon itself (no SSH — SSH is
494
+ // manual-only via UI, and the health worker's round is the one that
495
+ // opens a session).
253
496
  // 1. Ping (ICMP) — lightweight reachability check
254
497
  if (this.checkConfig.pingEnabled) {
255
498
  const ping = await this.remoteOps.ping(node.host, this.checkConfig.pingTimeout);
@@ -262,47 +505,92 @@ export class NodeManagerService extends EventEmitter {
262
505
  status.pingReachable = true;
263
506
  status.pingLatencyMs = null;
264
507
  }
265
- // 2. Netron TCP ping — check if omnitron daemon is running and responsive
266
- // Master connects to slave via SlaveConnector; if already connected,
267
- // the heartbeat confirms status. Otherwise try a quick TCP connect + ping.
268
- const port = node.daemonPort ?? 9700;
269
- try {
270
- const { Netron } = await import('@omnitron-dev/titan/netron');
271
- const { TcpTransport } = await import('@omnitron-dev/titan/netron/transport/tcp');
272
- const { createNullLogger } = await import('@omnitron-dev/titan/module/logger');
273
- const probeNetron = new Netron(createNullLogger(), { id: `probe-${node.host}` });
274
- probeNetron.registerTransport('tcp', () => new TcpTransport());
275
- const connectStart = Date.now();
276
- const peer = await Promise.race([
277
- probeNetron.connect(`tcp://${node.host}:${port}`, false),
278
- new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), this.checkConfig.omnitronCheckTimeout)),
279
- ]);
280
- // Ping via OmnitronDaemon service
281
- const daemon = await peer.queryInterface('OmnitronDaemon');
282
- const info = await daemon.ping();
283
- const latency = Date.now() - connectStart;
508
+ // 2. The daemon: asked over the mesh first, dialled directly second.
509
+ const answer = await this.askDaemon(node);
510
+ if (answer.ok) {
284
511
  status.omnitronConnected = true;
285
- status.sshConnected = false; // SSH not checked
286
- status.sshLatencyMs = null;
287
- if (info?.version)
288
- status.omnitronVersion = info.version;
289
- if (info?.pid)
290
- status.omnitronPid = info.pid;
291
- if (info?.uptime)
292
- status.omnitronUptime = info.uptime;
293
- this.logger.debug({ node: node.name, host: node.host, latencyMs: latency, version: info?.version }, 'Node check: Netron TCP ping OK');
294
- // Disconnect probe — SlaveConnector manages persistent connections
295
- await probeNetron.stop();
512
+ if (answer.info?.version)
513
+ status.omnitronVersion = answer.info.version;
514
+ if (answer.info?.pid)
515
+ status.omnitronPid = answer.info.pid;
516
+ if (answer.info?.uptime)
517
+ status.omnitronUptime = answer.info.uptime;
296
518
  }
297
- catch (err) {
298
- status.omnitronConnected = false;
299
- this.logger.debug({ node: node.name, host: node.host, port, error: err.message }, 'Node check: Netron TCP ping failed');
519
+ else {
520
+ // `null`, not `false`. Neither path reached the daemon, and that says
521
+ // nothing about whether it runs: a closed daemon port is the normal
522
+ // state of a hardened node, and a mesh link can be down while every
523
+ // app on the node serves. `false` reads as "the daemon is down" to
524
+ // every consumer — `node list`, `node check`, the console's dot —
525
+ // and that is the claim this check had no evidence for. The reasons
526
+ // travel in `omnitronError`, each naming its path.
527
+ status.omnitronConnected = null;
528
+ status.omnitronError = `Neither path reached the daemon — ${answer.reasons.join('; ')}`;
300
529
  }
301
530
  }
302
- this.statusCache.set(id, status);
303
- this.emit('node:status', id, status);
531
+ this.recordStatus(node, status);
304
532
  return status;
305
533
  }
534
+ /**
535
+ * Ask a node's daemon to answer `ping`, the way the master can reach it.
536
+ *
537
+ * The mesh first: it is the connection the master already holds, and for
538
+ * a node whose daemon port is firewalled it is the only one that works —
539
+ * over an SSH tunnel. The direct dial second, for a node outside the mesh
540
+ * (just added, or on a master whose mesh did not start) whose port IS open.
541
+ * Each failure is kept with the name of its path, because «connection
542
+ * timeout» alone does not say which door was shut.
543
+ */
544
+ async askDaemon(node) {
545
+ const port = node.daemonPort ?? 9700;
546
+ const reasons = [];
547
+ if (this.mesh) {
548
+ try {
549
+ const info = (await withTimeout(this.mesh.invokeOnSlave(node.host, port, 'OmnitronDaemon', 'ping', []), this.checkConfig.omnitronCheckTimeout));
550
+ this.logger.debug({ node: node.name, host: node.host, version: info?.version }, 'Node check: daemon answered over the mesh');
551
+ return { ok: true, via: 'mesh', info };
552
+ }
553
+ catch (err) {
554
+ reasons.push(`mesh: ${err.message}`);
555
+ }
556
+ }
557
+ else {
558
+ reasons.push('mesh: this daemon has no mesh connector');
559
+ }
560
+ let probeNetron = null;
561
+ try {
562
+ const { Netron } = await import('@omnitron-dev/titan/netron');
563
+ const { TcpTransport } = await import('@omnitron-dev/titan/netron/transport/tcp');
564
+ const { createNullLogger } = await import('@omnitron-dev/titan/module/logger');
565
+ const probe = new Netron(createNullLogger(), { id: `probe-${node.host}` });
566
+ probeNetron = probe;
567
+ probe.registerTransport('tcp', () => new TcpTransport());
568
+ const connectStart = Date.now();
569
+ const peer = await withTimeout(probe.connect(`tcp://${node.host}:${port}`, false), this.checkConfig.omnitronCheckTimeout);
570
+ // Ping via OmnitronDaemon service
571
+ const daemon = await peer.queryInterface('OmnitronDaemon');
572
+ const info = await daemon.ping();
573
+ this.logger.debug({ node: node.name, host: node.host, latencyMs: Date.now() - connectStart, version: info?.version }, 'Node check: daemon answered a direct dial');
574
+ return { ok: true, via: 'direct', info };
575
+ }
576
+ catch (err) {
577
+ reasons.push(`direct dial to ${node.host}:${port}: ${err.message}`);
578
+ this.logger.debug({ node: node.name, host: node.host, port, reasons }, 'Node check: no path reached the daemon');
579
+ return { ok: false, reasons };
580
+ }
581
+ finally {
582
+ // Stop the probe on EVERY path. It only ran on success, so each
583
+ // failed check — the common case for an offline node, once a minute,
584
+ // for ever — left a Netron instance with a registered TCP transport
585
+ // behind in the daemon.
586
+ if (probeNetron) {
587
+ try {
588
+ await probeNetron.stop();
589
+ }
590
+ catch { /* the probe is being discarded either way */ }
591
+ }
592
+ }
593
+ }
306
594
  /** Convert node to SSH target — used for manual SSH checks from UI */
307
595
  async nodeToSshTarget(node) {
308
596
  const target = {
@@ -325,16 +613,73 @@ export class NodeManagerService extends EventEmitter {
325
613
  }
326
614
  return target;
327
615
  }
616
+ /**
617
+ * Convert a registered node into something the deployer can reach.
618
+ *
619
+ * The bridge between the two registries. An operator registers machines
620
+ * here, in the console; deployment reads `stacks.nodes` out of a project
621
+ * config. Nothing joined them, which is half of why a machine added in the
622
+ * console could not be deployed to — the other half being that the deployer
623
+ * could not have used this node's credentials even if it had been handed
624
+ * one: it shelled out to `ssh -o BatchMode=yes`, and what this method
625
+ * returns is a password.
626
+ *
627
+ * The credentials come from `nodeToSshTarget`, which the manual SSH check
628
+ * already uses, so there is one place that knows how to unlock a node and
629
+ * both callers use it.
630
+ */
631
+ async nodeToDeployTarget(id) {
632
+ const node = this.nodes.get(id);
633
+ if (!node)
634
+ throw new Error(`Node not found: ${id}`);
635
+ if (node.isLocal) {
636
+ // Not a refusal on principle — a local daemon is deployed to by running
637
+ // omnitron, not by SSHing to yourself — but a refusal that says so,
638
+ // rather than a loopback SSH that fails for a reason the operator then
639
+ // has to work out.
640
+ throw new Error('The local node is this daemon; it is not deployed to over SSH.');
641
+ }
642
+ const ssh = await this.nodeToSshTarget(node);
643
+ const target = {
644
+ host: ssh.host,
645
+ label: node.name,
646
+ daemonPort: node.daemonPort ?? 9700,
647
+ };
648
+ if (ssh.port != null)
649
+ target.sshPort = ssh.port;
650
+ if (ssh.username)
651
+ target.username = ssh.username;
652
+ if (ssh.privateKey)
653
+ target.privateKey = ssh.privateKey;
654
+ if (ssh.passphrase)
655
+ target.passphrase = ssh.passphrase;
656
+ if (ssh.password)
657
+ target.password = ssh.password;
658
+ return target;
659
+ }
660
+ /**
661
+ * Check every node.
662
+ *
663
+ * Concurrent, bounded by the same `concurrency` the worker uses. It was a
664
+ * `for` loop with an `await` in it, so a fleet of twenty nodes with one
665
+ * unreachable host took the ping timeout plus the TCP timeout SERIALLY —
666
+ * twenty seconds of a thirty-second check interval spent on one node.
667
+ */
328
668
  async checkAllNodes() {
669
+ const ids = Array.from(this.nodes.keys());
329
670
  const results = [];
330
- for (const node of this.nodes.values()) {
331
- try {
332
- const status = await this.checkNodeStatus(node.id);
333
- results.push(status);
334
- }
335
- catch (err) {
336
- this.logger.warn({ nodeId: node.id, error: err.message }, 'Failed to check node');
337
- }
671
+ const width = Math.max(1, this.checkConfig.concurrency);
672
+ for (let i = 0; i < ids.length; i += width) {
673
+ const batch = ids.slice(i, i + width);
674
+ const settled = await Promise.allSettled(batch.map((id) => this.checkNodeStatus(id)));
675
+ settled.forEach((r, idx) => {
676
+ if (r.status === 'fulfilled') {
677
+ results.push(r.value);
678
+ }
679
+ else {
680
+ this.logger.warn({ nodeId: batch[idx], error: r.reason?.message }, 'Failed to check node');
681
+ }
682
+ });
338
683
  }
339
684
  return results;
340
685
  }
@@ -344,11 +689,19 @@ export class NodeManagerService extends EventEmitter {
344
689
  /**
345
690
  * Update the in-memory status cache from health-monitor worker summaries.
346
691
  * Called by daemon when worker sends IPC status batch.
692
+ *
693
+ * Only for nodes the registry holds. The worker's batch is its own memory,
694
+ * and it can name a node this registry removed — it did, every minute, for
695
+ * a node removed 82 minutes earlier — and writing that back put a status
696
+ * with no node behind it into `statusCache`, `summaryCache` and the
697
+ * heartbeat column of a row that no longer exists.
347
698
  */
348
699
  updateStatusCacheFromWorker(summaries) {
349
700
  for (const summary of summaries) {
350
701
  if (!summary.lastCheck)
351
702
  continue;
703
+ if (!this.nodes.has(summary.nodeId))
704
+ continue;
352
705
  const check = summary.lastCheck;
353
706
  const status = {
354
707
  nodeId: summary.nodeId,
@@ -377,7 +730,38 @@ export class NodeManagerService extends EventEmitter {
377
730
  status.omnitronError = check.omnitronError;
378
731
  this.statusCache.set(summary.nodeId, status);
379
732
  this.emit('node:status', summary.nodeId, status);
733
+ this.setSummary(summary);
734
+ }
735
+ }
736
+ /**
737
+ * Aggregated health, for a daemon serving checks without the worker.
738
+ *
739
+ * `triggerNodeCheck` used to return `[]` when the worker was absent, and an
740
+ * empty array on a page whose subject is the fleet reads as "no nodes".
741
+ */
742
+ getHealthSummaries(nodeId) {
743
+ if (nodeId) {
744
+ const one = this.summaryCache.get(nodeId);
745
+ return one ? [one] : [];
380
746
  }
747
+ return Array.from(this.summaryCache.values());
748
+ }
749
+ /**
750
+ * Note that one call to the health worker failed.
751
+ *
752
+ * Called by the RPC layer when a worker call throws. The call is served
753
+ * from the daemon instead; the worker keeps its proxy — a process that has
754
+ * gone is noticed by its exit handler, not guessed from one error. This
755
+ * exists so the reason appears in the daemon's log rather than only in the
756
+ * error text of whichever console button was pressed.
757
+ */
758
+ reportWorkerUnavailable(method, err) {
759
+ this.logger.warn({ method, error: err.message }, 'Health monitor worker did not answer this call — serving it from the daemon');
760
+ this.emit('worker:unavailable', method, err);
761
+ }
762
+ /** Report a non-fatal failure in node bookkeeping, with the reason. */
763
+ reportProblem(operation, err) {
764
+ this.logger.warn({ operation, error: err.message }, 'Node maintenance step failed');
381
765
  }
382
766
  /**
383
767
  * Convert current node list to serializable check targets for the worker.
@@ -411,7 +795,7 @@ export class NodeManagerService extends EventEmitter {
411
795
  if (node.hasPassword) {
412
796
  const val = await this.getSecret(node.id, 'password');
413
797
  if (val)
414
- target.sshPassphrase = val; // password auth as passphrase for xec
798
+ target.sshPassword = val;
415
799
  }
416
800
  targets.push(target);
417
801
  }
@@ -423,7 +807,8 @@ export class NodeManagerService extends EventEmitter {
423
807
  secretKey(nodeId, field) {
424
808
  return `node:${nodeId}:${field}`;
425
809
  }
426
- async getSecret(nodeId, field) {
810
+ /** The vault's own answer, with no in-memory fallback. */
811
+ async readVault(nodeId, field) {
427
812
  if (!this.secrets)
428
813
  return null;
429
814
  try {
@@ -433,6 +818,18 @@ export class NodeManagerService extends EventEmitter {
433
818
  return null;
434
819
  }
435
820
  }
821
+ async getSecret(nodeId, field) {
822
+ const key = this.secretKey(nodeId, field);
823
+ if (this.secrets) {
824
+ try {
825
+ const stored = await this.secrets.get(key);
826
+ if (stored)
827
+ return stored;
828
+ }
829
+ catch { /* fall through to the pending value, if any */ }
830
+ }
831
+ return this.pendingSecrets.get(key) ?? null;
832
+ }
436
833
  async setSecret(nodeId, field, value) {
437
834
  if (!this.secrets) {
438
835
  this.logger.warn({ nodeId, field }, 'SecretsService not available — secret not stored');
@@ -449,18 +846,26 @@ export class NodeManagerService extends EventEmitter {
449
846
  catch { /* non-critical */ }
450
847
  }
451
848
  /**
452
- * Synchronously populate local node status at construction time.
453
- * We ARE the daemon — no RPC/socket needed, just read process info.
849
+ * Status of the machine this daemon runs on.
850
+ *
851
+ * We ARE the daemon — no RPC or socket needed, just read process info, and
852
+ * read it now rather than at construction. The version came from a string
853
+ * literal `'0.1.0'` while the package was at 0.2.0, so the fleet view
854
+ * reported a version the daemon has never been; it is `CLI_VERSION` now,
855
+ * the same source `omnitron status` uses.
856
+ *
857
+ * The role is `master` unconditionally, and that is correct rather than
858
+ * lazy: this service is only constructed on a non-slave daemon.
454
859
  */
455
- initLocalStatus() {
456
- this.statusCache.set(LOCAL_NODE_ID, {
860
+ localStatus() {
861
+ return {
457
862
  nodeId: LOCAL_NODE_ID,
458
863
  pingReachable: true,
459
864
  pingLatencyMs: 0,
460
865
  sshConnected: true,
461
866
  sshLatencyMs: 0,
462
867
  omnitronConnected: true,
463
- omnitronVersion: '0.1.0',
868
+ omnitronVersion: CLI_VERSION,
464
869
  omnitronPid: process.pid,
465
870
  omnitronUptime: process.uptime() * 1000,
466
871
  omnitronRole: 'master',
@@ -471,34 +876,243 @@ export class NodeManagerService extends EventEmitter {
471
876
  release: os.release(),
472
877
  },
473
878
  checkedAt: new Date().toISOString(),
879
+ };
880
+ }
881
+ // ===========================================================================
882
+ // Status bookkeeping
883
+ // ===========================================================================
884
+ /** Record a check this service performed, and derive its health summary. */
885
+ recordStatus(node, status) {
886
+ this.statusCache.set(node.id, status);
887
+ this.emit('node:status', node.id, status);
888
+ const previous = this.summaryCache.get(node.id);
889
+ const reachable = status.sshConnected || status.pingReachable || status.omnitronConnected;
890
+ const offlineTimeout = node.offlineTimeout ?? DEFAULT_OFFLINE_TIMEOUT_MS;
891
+ let health;
892
+ if (status.omnitronConnected) {
893
+ health = 'online';
894
+ }
895
+ else if (reachable) {
896
+ health = 'degraded';
897
+ }
898
+ else {
899
+ const lastSeen = previous?.lastSeenOnline;
900
+ health = lastSeen && Date.now() - Date.parse(lastSeen) < offlineTimeout ? 'degraded' : 'offline';
901
+ }
902
+ this.setSummary({
903
+ nodeId: node.id,
904
+ status: health,
905
+ lastCheck: {
906
+ nodeId: node.id,
907
+ checkedAt: status.checkedAt,
908
+ checkDurationMs: 0,
909
+ pingReachable: status.pingReachable,
910
+ pingLatencyMs: status.pingLatencyMs,
911
+ pingError: status.pingError ?? null,
912
+ sshConnected: status.sshConnected,
913
+ sshLatencyMs: status.sshLatencyMs,
914
+ sshError: status.sshError ?? null,
915
+ omnitronConnected: status.omnitronConnected,
916
+ omnitronVersion: status.omnitronVersion ?? null,
917
+ omnitronPid: status.omnitronPid ?? null,
918
+ omnitronUptime: status.omnitronUptime ?? null,
919
+ omnitronRole: status.omnitronRole ?? null,
920
+ omnitronError: status.omnitronError ?? null,
921
+ os: status.os ?? null,
922
+ },
923
+ lastSeenOnline: reachable ? status.checkedAt : (previous?.lastSeenOnline ?? null),
924
+ consecutiveFailures: reachable ? 0 : (previous?.consecutiveFailures ?? 0) + 1,
474
925
  });
475
926
  }
927
+ /**
928
+ * Store a summary, write it to the row, and announce a change of state.
929
+ *
930
+ * `nodes.status` and `nodes.last_heartbeat` are columns the schema declares,
931
+ * `selectNodesSync` reads back, and nothing ever wrote: every row on a live
932
+ * daemon said `status = 'unknown'` with a null heartbeat, because the only
933
+ * writer — `touchNodeHeartbeatSync` — had no callers. The upsert filled
934
+ * them with its own `'unknown'` default on every save.
935
+ *
936
+ * What this buys beyond tidiness: `lastSeenOnline` survives a daemon
937
+ * restart, so the offline grace period is measured from when the node was
938
+ * actually last seen rather than from boot.
939
+ */
940
+ setSummary(summary) {
941
+ const previous = this.summaryCache.get(summary.nodeId) ?? null;
942
+ this.summaryCache.set(summary.nodeId, summary);
943
+ try {
944
+ this.store.touchNodeHeartbeatSync(summary.nodeId, summary.status, summary.lastCheck?.checkedAt ?? new Date().toISOString());
945
+ }
946
+ catch { /* the in-memory answer is still correct */ }
947
+ if (previous?.status === summary.status)
948
+ return;
949
+ const transition = {
950
+ nodeId: summary.nodeId,
951
+ status: summary.status,
952
+ previousStatus: previous?.status ?? null,
953
+ };
954
+ this.emit('node:health', transition);
955
+ }
476
956
  // ===========================================================================
477
957
  // Persistence
478
958
  // ===========================================================================
479
959
  load() {
960
+ /** Rows found carrying a plaintext secret; healed after the loop. */
961
+ const leaked = [];
480
962
  try {
481
- if (fs.existsSync(NODES_FILE)) {
482
- const data = JSON.parse(fs.readFileSync(NODES_FILE, 'utf-8'));
483
- if (Array.isArray(data.nodes)) {
484
- for (const node of data.nodes) {
485
- this.nodes.set(node.id, node);
963
+ // First-pass: read from SQLite. Each row's `metadata` column
964
+ // holds the full INode JSON; the denormalised columns are for
965
+ // future queries (status filters, by-host lookups, etc.).
966
+ const rows = this.store.selectNodesSync();
967
+ for (const row of rows) {
968
+ if (!row.metadata)
969
+ continue;
970
+ try {
971
+ const raw = JSON.parse(row.metadata);
972
+ const { node, strays } = splitStoredSecrets(raw);
973
+ this.nodes.set(node.id, node);
974
+ if (strays.length > 0) {
975
+ for (const stray of strays)
976
+ this.pendingSecrets.set(this.secretKey(node.id, stray.field), stray.value);
977
+ leaked.push({ node, strays });
978
+ }
979
+ // Restore the last known health, but NOT a status reading: a
980
+ // reachability answer from a previous daemon is not a current one,
981
+ // and the console has no way to tell them apart on the dots. What
982
+ // is worth keeping is when the node was last up, which is what the
983
+ // offline grace period is measured against.
984
+ if (row.status && row.status !== 'unknown') {
985
+ this.summaryCache.set(node.id, {
986
+ nodeId: node.id,
987
+ status: row.status,
988
+ lastCheck: null,
989
+ lastSeenOnline: row.status === 'offline' ? null : row.last_heartbeat ?? null,
990
+ consecutiveFailures: 0,
991
+ });
486
992
  }
487
993
  }
994
+ catch {
995
+ // Corrupt row — skip and let the next mutation overwrite.
996
+ }
997
+ }
998
+ // One-shot legacy import. If the SQLite table is empty but the
999
+ // pre-T-7 nodes.json file exists, migrate it in-place. The
1000
+ // existing file is then unlinked so subsequent boots skip the
1001
+ // branch.
1002
+ if (this.nodes.size === 0 && fs.existsSync(NODES_FILE)) {
1003
+ try {
1004
+ const data = JSON.parse(fs.readFileSync(NODES_FILE, 'utf-8'));
1005
+ if (Array.isArray(data.nodes)) {
1006
+ for (const node of data.nodes) {
1007
+ this.nodes.set(node.id, node);
1008
+ this.persistNode(node);
1009
+ }
1010
+ }
1011
+ try {
1012
+ fs.unlinkSync(NODES_FILE);
1013
+ }
1014
+ catch { /* best-effort */ }
1015
+ }
1016
+ catch (err) {
1017
+ this.logger.warn({ error: err.message }, 'Legacy nodes.json migration failed — leaving file in place');
1018
+ }
488
1019
  }
489
1020
  }
490
1021
  catch (err) {
491
- this.logger.warn({ error: err.message }, 'Failed to load nodes file');
1022
+ this.logger.warn({ error: err.message }, 'Failed to load nodes from store');
492
1023
  }
1024
+ if (leaked.length > 0)
1025
+ void this.healLeakedSecrets(leaked);
1026
+ this.loadCheckConfig();
493
1027
  }
494
- save() {
1028
+ /**
1029
+ * Move a plaintext secret out of a node row and into the vault.
1030
+ *
1031
+ * Observed on a live daemon: a node row whose `metadata` JSON contained
1032
+ * `"sshPassphrase": "<the operator's actual passphrase>"` next to
1033
+ * `"hasPassphrase": true`. An older `updateNode` spread its whole input
1034
+ * into the node — the destructure that stops that was added afterwards, and
1035
+ * it fixed new writes without touching rows already written. `listNodes`
1036
+ * then spread the parsed row onto the wire, so the passphrase went to every
1037
+ * caller with the VIEWER role, and to `omnitron node list`.
1038
+ *
1039
+ * Two things are needed and they are not the same: the wire shape is now
1040
+ * built field by field (`toWireNode`), which stops the leak for any
1041
+ * residue, present or future; and this moves the value to where it should
1042
+ * have been, so the row itself stops holding it.
1043
+ */
1044
+ async healLeakedSecrets(leaked) {
1045
+ for (const { node, strays } of leaked) {
1046
+ for (const { field, value } of strays) {
1047
+ this.logger.warn({ nodeId: node.id, field }, 'Node row held a plaintext SSH secret — moving it to the secret store');
1048
+ // Read the VAULT, not `getSecret`: that one falls back to
1049
+ // `pendingSecrets`, which is where this value already is — so asking
1050
+ // it whether the secret is stored answers "yes" about the copy we are
1051
+ // trying to store, and the write never happens.
1052
+ const existing = await this.readVault(node.id, field);
1053
+ if (!existing) {
1054
+ if (!this.secrets) {
1055
+ // Nothing to migrate into. The row keeps the value for now — the
1056
+ // node would otherwise stop authenticating — but it no longer
1057
+ // reaches the wire, which is the part that matters.
1058
+ this.logger.error({ nodeId: node.id, field }, 'No secret store available — plaintext secret left in the node row');
1059
+ continue;
1060
+ }
1061
+ await this.setSecret(node.id, field, value);
1062
+ }
1063
+ }
1064
+ // Rewrite the row from the sanitised node.
1065
+ this.persistNode(node);
1066
+ for (const { field } of strays)
1067
+ this.pendingSecrets.delete(this.secretKey(node.id, field));
1068
+ }
1069
+ }
1070
+ /** Restore the operator's check configuration, if one was ever set. */
1071
+ loadCheckConfig() {
495
1072
  try {
496
- fs.mkdirSync(path.dirname(NODES_FILE), { recursive: true });
497
- const data = { nodes: Array.from(this.nodes.values()) };
498
- fs.writeFileSync(NODES_FILE, JSON.stringify(data, null, 2));
1073
+ const stored = this.store.kvGetSync(CHECK_CONFIG_KEY);
1074
+ if (!stored)
1075
+ return;
1076
+ this.checkConfig = normalizeCheckConfig({ ...DEFAULT_CHECK_CONFIG, ...stored });
499
1077
  }
500
1078
  catch (err) {
501
- this.logger.warn({ error: err.message }, 'Failed to save nodes file');
1079
+ this.logger.warn({ error: err.message }, 'Failed to load node check config — using defaults');
1080
+ }
1081
+ }
1082
+ /**
1083
+ * Persist a single node to SQLite. Called on add / update /
1084
+ * status-touch. Pre-T-7 every mutation rewrote the entire
1085
+ * registry JSON file; now it's a single atomic UPSERT.
1086
+ */
1087
+ persistNode(node) {
1088
+ try {
1089
+ // Carry the status forward. `upsertNodeSync` defaults it to `'unknown'`,
1090
+ // so a `save()` triggered by an unrelated edit used to erase what the
1091
+ // last check had established.
1092
+ const known = this.summaryCache.get(node.id);
1093
+ this.store.upsertNodeSync({
1094
+ id: node.id,
1095
+ name: node.name,
1096
+ host: node.host,
1097
+ port: node.daemonPort,
1098
+ role: node.isLocal ? 'master' : 'slave',
1099
+ status: known?.status ?? 'unknown',
1100
+ last_heartbeat: known?.lastCheck?.checkedAt ?? null,
1101
+ metadata: node,
1102
+ });
1103
+ }
1104
+ catch (err) {
1105
+ this.logger.warn({ id: node.id, error: err.message }, 'Failed to persist node');
1106
+ }
1107
+ }
1108
+ /**
1109
+ * Persist every node currently held in memory. Used after a
1110
+ * batch mutation that affected multiple rows (the previous
1111
+ * fs.writeFileSync semantics).
1112
+ */
1113
+ save() {
1114
+ for (const node of this.nodes.values()) {
1115
+ this.persistNode(node);
502
1116
  }
503
1117
  }
504
1118
  ensureLocalNode() {
@@ -528,6 +1142,94 @@ export class NodeManagerService extends EventEmitter {
528
1142
  // =============================================================================
529
1143
  // Helpers
530
1144
  // =============================================================================
1145
+ /**
1146
+ * The node as it may be sent to a caller.
1147
+ *
1148
+ * Built field by field on purpose. `listNodes` used to spread the object
1149
+ * parsed out of the `metadata` column, which means the payload was whatever
1150
+ * happened to have been written there — and on a live daemon that included
1151
+ * an SSH passphrase in plaintext. A DTO is a promise about what is returned;
1152
+ * spreading a JSON blob delegates that promise to whoever last wrote the row.
1153
+ */
1154
+ function toWireNode(node) {
1155
+ const wire = {
1156
+ id: node.id,
1157
+ name: node.name,
1158
+ host: node.host,
1159
+ sshPort: node.sshPort,
1160
+ sshUser: node.sshUser,
1161
+ sshAuthMethod: node.sshAuthMethod,
1162
+ runtime: node.runtime,
1163
+ daemonPort: node.daemonPort,
1164
+ tags: node.tags ?? [],
1165
+ isLocal: node.isLocal,
1166
+ createdAt: node.createdAt,
1167
+ updatedAt: node.updatedAt,
1168
+ };
1169
+ // The key is a PATH or key content chosen by the operator; the booleans say
1170
+ // only whether a secret exists. Neither is a secret itself.
1171
+ if (node.sshPrivateKey !== undefined)
1172
+ wire.sshPrivateKey = node.sshPrivateKey;
1173
+ if (node.hasPassphrase !== undefined)
1174
+ wire.hasPassphrase = node.hasPassphrase;
1175
+ if (node.hasPassword !== undefined)
1176
+ wire.hasPassword = node.hasPassword;
1177
+ if (node.offlineTimeout !== undefined)
1178
+ wire.offlineTimeout = node.offlineTimeout;
1179
+ return wire;
1180
+ }
1181
+ /** Separate a stored node from any plaintext secret its row still carries. */
1182
+ function splitStoredSecrets(raw) {
1183
+ const { sshPassphrase, sshPassword, ...rest } = raw;
1184
+ const node = rest;
1185
+ const strays = [];
1186
+ if (typeof sshPassphrase === 'string' && sshPassphrase) {
1187
+ node.hasPassphrase = true;
1188
+ strays.push({ field: 'passphrase', value: sshPassphrase });
1189
+ }
1190
+ if (typeof sshPassword === 'string' && sshPassword) {
1191
+ node.hasPassword = true;
1192
+ strays.push({ field: 'password', value: sshPassword });
1193
+ }
1194
+ return { node, strays };
1195
+ }
1196
+ /** Fallback offline timeout, matching the health monitor's own default. */
1197
+ const DEFAULT_OFFLINE_TIMEOUT_MS = 90_000;
1198
+ /** A TCP port the daemon will actually try to connect to. */
1199
+ function assertPort(kind, value) {
1200
+ if (!Number.isInteger(value) || value < 1 || value > 65_535) {
1201
+ throw new Error(`Invalid ${kind}: ${JSON.stringify(value)}. Expected an integer between 1 and 65535.`);
1202
+ }
1203
+ return value;
1204
+ }
1205
+ /** Reject a promise that has not settled within `ms`. */
1206
+ async function withTimeout(promise, ms) {
1207
+ let timer;
1208
+ try {
1209
+ return await Promise.race([
1210
+ promise,
1211
+ new Promise((_, reject) => {
1212
+ timer = setTimeout(() => reject(new Error(`Timed out after ${ms}ms`)), ms);
1213
+ }),
1214
+ ]);
1215
+ }
1216
+ finally {
1217
+ if (timer)
1218
+ clearTimeout(timer);
1219
+ }
1220
+ }
1221
+ /** Read the first `bytes` of a file without loading the whole thing. */
1222
+ function readFileHead(filePath, bytes) {
1223
+ const fd = fs.openSync(filePath, 'r');
1224
+ try {
1225
+ const buf = Buffer.alloc(bytes);
1226
+ const read = fs.readSync(fd, buf, 0, bytes, 0);
1227
+ return buf.subarray(0, read).toString('utf-8');
1228
+ }
1229
+ finally {
1230
+ fs.closeSync(fd);
1231
+ }
1232
+ }
531
1233
  /**
532
1234
  * Read SSH private key file contents.
533
1235
  * If the value is already key content (starts with -----BEGIN), return as-is.