@underpostnet/cyberia 3.2.80

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 (821) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.example +144 -0
  3. package/.github/workflows/cyberia-client.cd.yml +40 -0
  4. package/.github/workflows/cyberia-server.cd.yml +40 -0
  5. package/.github/workflows/docker-image.cyberia-client.ci.yml +71 -0
  6. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +70 -0
  7. package/.github/workflows/docker-image.cyberia-server.ci.yml +71 -0
  8. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +71 -0
  9. package/.github/workflows/docker-image.engine-cyberia.ci.yml +53 -0
  10. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +53 -0
  11. package/.github/workflows/engine-cyberia.cd.yml +157 -0
  12. package/.github/workflows/engine-cyberia.ci.yml +125 -0
  13. package/.github/workflows/ghpkg.ci.yml +160 -0
  14. package/.github/workflows/gitlab.ci.yml +20 -0
  15. package/.github/workflows/hardhat.ci.yml +82 -0
  16. package/.github/workflows/npmpkg.ci.yml +126 -0
  17. package/.github/workflows/publish.ci.yml +87 -0
  18. package/.github/workflows/publish.cyberia.ci.yml +79 -0
  19. package/.github/workflows/pwa-microservices-template-page.cd.yml +65 -0
  20. package/.github/workflows/pwa-microservices-template-test.ci.yml +33 -0
  21. package/.github/workflows/release.cd.yml +46 -0
  22. package/.nycrc +9 -0
  23. package/.prettierignore +12 -0
  24. package/.prettierrc +9 -0
  25. package/.vscode/extensions.json +10 -0
  26. package/.vscode/settings.json +26 -0
  27. package/CHANGELOG.md +2516 -0
  28. package/CLI-HELP.md +1099 -0
  29. package/Dockerfile +161 -0
  30. package/Dockerfile.dev +161 -0
  31. package/Dockerfile.test +165 -0
  32. package/LICENSE +21 -0
  33. package/README.md +259 -0
  34. package/baremetal/commission-workflows.json +211 -0
  35. package/baremetal/packer-workflows.json +24 -0
  36. package/bin/build.js +261 -0
  37. package/bin/build.template.js +33 -0
  38. package/bin/cyberia.js +5627 -0
  39. package/bin/deploy.js +1547 -0
  40. package/bin/index.js +5627 -0
  41. package/bump.config.js +27 -0
  42. package/compose.env +144 -0
  43. package/conf.js +952 -0
  44. package/deployment.yaml +418 -0
  45. package/docker-compose.yml +434 -0
  46. package/examples/static-page/README.md +150 -0
  47. package/examples/static-page/ssr-components/CustomPage.js +554 -0
  48. package/examples/static-page/static-config-example.json +57 -0
  49. package/hardhat/.env.example +31 -0
  50. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  51. package/hardhat/deployments/.gitkeep +0 -0
  52. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  53. package/hardhat/hardhat.config.js +136 -0
  54. package/hardhat/ignition/modules/.gitkeep +0 -0
  55. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  56. package/hardhat/networks/besu-object-layer.network.json +138 -0
  57. package/hardhat/package-lock.json +2871 -0
  58. package/hardhat/package.json +43 -0
  59. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  60. package/hardhat/test/ObjectLayerToken.js +696 -0
  61. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  62. package/hardhat/types/ethers-contracts/common.ts +92 -0
  63. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  64. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  65. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  66. package/hardhat/types/ethers-contracts/index.ts +6 -0
  67. package/ipfs/configure-ipfs.sh +13 -0
  68. package/jsconfig.json +9 -0
  69. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +48 -0
  70. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +48 -0
  71. package/manifests/deployment/adminer/deployment.yaml +32 -0
  72. package/manifests/deployment/adminer/kustomization.yaml +7 -0
  73. package/manifests/deployment/adminer/service.yaml +13 -0
  74. package/manifests/deployment/dd-cyberia-development/deployment.yaml +418 -0
  75. package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
  76. package/manifests/deployment/dd-cyberia-development/proxy.yaml +189 -0
  77. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +164 -0
  78. package/manifests/deployment/dd-default-development/deployment.yaml +163 -0
  79. package/manifests/deployment/dd-default-development/proxy.yaml +46 -0
  80. package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
  81. package/manifests/deployment/fastapi/backend-service.yml +19 -0
  82. package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
  83. package/manifests/deployment/fastapi/frontend-service.yml +15 -0
  84. package/manifests/deployment/fastapi/initial_data.sh +8 -0
  85. package/manifests/deployment/kafka/deployment.yaml +67 -0
  86. package/manifests/deployment/mongo-express/deployment.yaml +62 -0
  87. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  88. package/manifests/deployment/playwright/deployment.yaml +52 -0
  89. package/manifests/deployment/spark/spark-pi-py.yaml +20 -0
  90. package/manifests/deployment/tensorflow/tf-gpu-test.yaml +63 -0
  91. package/manifests/envoy-service-nodeport.yaml +22 -0
  92. package/manifests/grafana/deployment.yaml +64 -0
  93. package/manifests/grafana/kustomization.yaml +7 -0
  94. package/manifests/grafana/pvc.yaml +12 -0
  95. package/manifests/grafana/service.yaml +14 -0
  96. package/manifests/grafana/storage-class.yaml +9 -0
  97. package/manifests/ipfs/configmap.yaml +64 -0
  98. package/manifests/ipfs/headless-service.yaml +35 -0
  99. package/manifests/ipfs/kustomization.yaml +8 -0
  100. package/manifests/ipfs/statefulset.yaml +149 -0
  101. package/manifests/ipfs/storage-class.yaml +9 -0
  102. package/manifests/kind-config-dev.yaml +20 -0
  103. package/manifests/kind-config.yaml +12 -0
  104. package/manifests/kubeadm-calico-config.yaml +14 -0
  105. package/manifests/letsencrypt-prod.yaml +14 -0
  106. package/manifests/lxd/lxd-admin-profile.yaml +26 -0
  107. package/manifests/lxd/lxd-preseed.yaml +30 -0
  108. package/manifests/mariadb/kustomization.yaml +9 -0
  109. package/manifests/mariadb/pv.yaml +12 -0
  110. package/manifests/mariadb/pvc.yaml +10 -0
  111. package/manifests/mariadb/service.yaml +10 -0
  112. package/manifests/mariadb/statefulset.yaml +56 -0
  113. package/manifests/mariadb/storage-class.yaml +10 -0
  114. package/manifests/mongodb/headless-service.yaml +10 -0
  115. package/manifests/mongodb/kustomization.yaml +11 -0
  116. package/manifests/mongodb/pv-pvc.yaml +59 -0
  117. package/manifests/mongodb/statefulset.yaml +113 -0
  118. package/manifests/mongodb/storage-class.yaml +9 -0
  119. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  120. package/manifests/mongodb-4.4/kustomization.yaml +9 -0
  121. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  122. package/manifests/mongodb-4.4/pv-pvc.yaml +19 -0
  123. package/manifests/mongodb-4.4/service-deployment.yaml +61 -0
  124. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  125. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  126. package/manifests/mysql/kustomization.yaml +7 -0
  127. package/manifests/mysql/pv-pvc.yaml +27 -0
  128. package/manifests/mysql/statefulset.yaml +55 -0
  129. package/manifests/postgresql/configmap.yaml +9 -0
  130. package/manifests/postgresql/kustomization.yaml +10 -0
  131. package/manifests/postgresql/pv.yaml +15 -0
  132. package/manifests/postgresql/pvc.yaml +13 -0
  133. package/manifests/postgresql/service.yaml +10 -0
  134. package/manifests/postgresql/statefulset.yaml +37 -0
  135. package/manifests/prometheus/deployment.yaml +82 -0
  136. package/manifests/pv-pvc-dd.yaml +34 -0
  137. package/manifests/valkey/kustomization.yaml +7 -0
  138. package/manifests/valkey/service.yaml +10 -0
  139. package/manifests/valkey/statefulset.yaml +37 -0
  140. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  141. package/mongodb/entrypoint.sh +76 -0
  142. package/nginx.conf +128 -0
  143. package/nodemon.json +6 -0
  144. package/package.json +101 -0
  145. package/packer/images/Rocky9Amd64/Makefile +62 -0
  146. package/packer/images/Rocky9Amd64/QUICKSTART.md +113 -0
  147. package/packer/images/Rocky9Amd64/README.md +122 -0
  148. package/packer/images/Rocky9Amd64/http/rocky9.ks.pkrtpl.hcl +114 -0
  149. package/packer/images/Rocky9Amd64/rocky9.pkr.hcl +164 -0
  150. package/packer/images/Rocky9Arm64/Makefile +69 -0
  151. package/packer/images/Rocky9Arm64/README.md +122 -0
  152. package/packer/images/Rocky9Arm64/http/rocky9.ks.pkrtpl.hcl +114 -0
  153. package/packer/images/Rocky9Arm64/rocky9.pkr.hcl +171 -0
  154. package/packer/scripts/fuse-nbd +64 -0
  155. package/packer/scripts/fuse-tar-root +63 -0
  156. package/proxy.yaml +189 -0
  157. package/pv-pvc.yaml +164 -0
  158. package/scripts/device-scan.sh +65 -0
  159. package/scripts/disk-clean.sh +182 -0
  160. package/scripts/disk-devices.sh +13 -0
  161. package/scripts/gen-fqdns.sh +14 -0
  162. package/scripts/gpu-diag.sh +19 -0
  163. package/scripts/ip-info.sh +118 -0
  164. package/scripts/ipxe-setup.sh +200 -0
  165. package/scripts/k3s-node-setup.sh +124 -0
  166. package/scripts/kubeadm-node-setup.sh +317 -0
  167. package/scripts/link-local-underpost-cli.sh +6 -0
  168. package/scripts/lxd-vm-setup.sh +208 -0
  169. package/scripts/maas-nat-firewalld.sh +145 -0
  170. package/scripts/maas-setup.sh +135 -0
  171. package/scripts/maas-upload-boot-resource.sh +183 -0
  172. package/scripts/nat-iptables.sh +111 -0
  173. package/scripts/nvim.sh +91 -0
  174. package/scripts/packer-init-vars-file.sh +40 -0
  175. package/scripts/packer-setup.sh +289 -0
  176. package/scripts/ports-ls.sh +33 -0
  177. package/scripts/quick-tftp.sh +19 -0
  178. package/scripts/rhel-grpc-setup.sh +56 -0
  179. package/scripts/rocky-kickstart.sh +986 -0
  180. package/scripts/rocky-pwa.sh +200 -0
  181. package/scripts/rocky-setup.sh +106 -0
  182. package/scripts/rpmfusion-ffmpeg-setup.sh +32 -0
  183. package/scripts/ssl.sh +170 -0
  184. package/scripts/test-monitor.sh +248 -0
  185. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +30 -0
  186. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +155 -0
  187. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +39 -0
  188. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +382 -0
  189. package/src/api/core/core.controller.js +8 -0
  190. package/src/api/core/core.model.js +11 -0
  191. package/src/api/core/core.router.js +23 -0
  192. package/src/api/core/core.service.js +30 -0
  193. package/src/api/crypto/crypto.controller.js +10 -0
  194. package/src/api/crypto/crypto.model.js +23 -0
  195. package/src/api/crypto/crypto.router.js +23 -0
  196. package/src/api/crypto/crypto.service.js +64 -0
  197. package/src/api/cyberia-action/cyberia-action.controller.js +8 -0
  198. package/src/api/cyberia-action/cyberia-action.model.js +79 -0
  199. package/src/api/cyberia-action/cyberia-action.router.js +21 -0
  200. package/src/api/cyberia-action/cyberia-action.service.js +58 -0
  201. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +27 -0
  202. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +100 -0
  203. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +70 -0
  204. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
  205. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +8 -0
  206. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  207. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +20 -0
  208. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +57 -0
  209. package/src/api/cyberia-entity/cyberia-entity.controller.js +6 -0
  210. package/src/api/cyberia-entity/cyberia-entity.model.js +25 -0
  211. package/src/api/cyberia-entity/cyberia-entity.router.js +17 -0
  212. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  213. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +6 -0
  214. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
  215. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -0
  216. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
  217. package/src/api/cyberia-instance/cyberia-fallback-world.js +337 -0
  218. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +57 -0
  219. package/src/api/cyberia-instance/cyberia-instance-map.service.js +583 -0
  220. package/src/api/cyberia-instance/cyberia-instance.controller.js +42 -0
  221. package/src/api/cyberia-instance/cyberia-instance.model.js +117 -0
  222. package/src/api/cyberia-instance/cyberia-instance.router.js +75 -0
  223. package/src/api/cyberia-instance/cyberia-instance.service.js +190 -0
  224. package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
  225. package/src/api/cyberia-instance/cyberia-world-generator.js +618 -0
  226. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +6 -0
  227. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +200 -0
  228. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +17 -0
  229. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
  230. package/src/api/cyberia-map/cyberia-map.controller.js +6 -0
  231. package/src/api/cyberia-map/cyberia-map.model.js +33 -0
  232. package/src/api/cyberia-map/cyberia-map.router.js +19 -0
  233. package/src/api/cyberia-map/cyberia-map.service.js +76 -0
  234. package/src/api/cyberia-quest/cyberia-quest.controller.js +9 -0
  235. package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
  236. package/src/api/cyberia-quest/cyberia-quest.router.js +26 -0
  237. package/src/api/cyberia-quest/cyberia-quest.service.js +97 -0
  238. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +6 -0
  239. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
  240. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +21 -0
  241. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
  242. package/src/api/cyberia-saga/cyberia-saga.controller.js +6 -0
  243. package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
  244. package/src/api/cyberia-saga/cyberia-saga.router.js +17 -0
  245. package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
  246. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +1076 -0
  247. package/src/api/cyberia-skill/cyberia-skill.controller.js +6 -0
  248. package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
  249. package/src/api/cyberia-skill/cyberia-skill.router.js +17 -0
  250. package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
  251. package/src/api/default/default.controller.js +6 -0
  252. package/src/api/default/default.model.js +20 -0
  253. package/src/api/default/default.router.js +21 -0
  254. package/src/api/default/default.service.js +42 -0
  255. package/src/api/document/document.controller.js +9 -0
  256. package/src/api/document/document.model.js +95 -0
  257. package/src/api/document/document.router.js +32 -0
  258. package/src/api/document/document.service.js +633 -0
  259. package/src/api/file/file.controller.js +15 -0
  260. package/src/api/file/file.model.js +127 -0
  261. package/src/api/file/file.ref.json +39 -0
  262. package/src/api/file/file.router.js +36 -0
  263. package/src/api/file/file.service.js +499 -0
  264. package/src/api/instance/instance.controller.js +8 -0
  265. package/src/api/instance/instance.model.js +34 -0
  266. package/src/api/instance/instance.router.js +27 -0
  267. package/src/api/instance/instance.service.js +75 -0
  268. package/src/api/ipfs/ipfs.controller.js +8 -0
  269. package/src/api/ipfs/ipfs.model.js +77 -0
  270. package/src/api/ipfs/ipfs.router.js +26 -0
  271. package/src/api/ipfs/ipfs.service.js +145 -0
  272. package/src/api/object-layer/object-layer.controller.js +18 -0
  273. package/src/api/object-layer/object-layer.model.js +200 -0
  274. package/src/api/object-layer/object-layer.router.js +729 -0
  275. package/src/api/object-layer/object-layer.service.js +894 -0
  276. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +6 -0
  277. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +93 -0
  278. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +17 -0
  279. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +46 -0
  280. package/src/api/test/test.controller.js +14 -0
  281. package/src/api/test/test.model.js +14 -0
  282. package/src/api/test/test.router.js +23 -0
  283. package/src/api/test/test.service.js +35 -0
  284. package/src/api/types.js +24 -0
  285. package/src/api/user/guest.service.js +100 -0
  286. package/src/api/user/postman_collection.json +216 -0
  287. package/src/api/user/user.build.js +16 -0
  288. package/src/api/user/user.controller.js +35 -0
  289. package/src/api/user/user.model.js +142 -0
  290. package/src/api/user/user.router.js +367 -0
  291. package/src/api/user/user.service.js +582 -0
  292. package/src/api.js +23 -0
  293. package/src/cli/baremetal.js +3947 -0
  294. package/src/cli/cloud-init.js +673 -0
  295. package/src/cli/cluster.js +1395 -0
  296. package/src/cli/db.js +1533 -0
  297. package/src/cli/deploy.js +1542 -0
  298. package/src/cli/docker-compose.js +802 -0
  299. package/src/cli/env.js +177 -0
  300. package/src/cli/fs.js +380 -0
  301. package/src/cli/image.js +389 -0
  302. package/src/cli/index.js +1059 -0
  303. package/src/cli/ipfs.js +182 -0
  304. package/src/cli/kickstart.js +271 -0
  305. package/src/cli/kubectl.js +214 -0
  306. package/src/cli/lxd.js +1232 -0
  307. package/src/cli/monitor.js +659 -0
  308. package/src/cli/release.js +595 -0
  309. package/src/cli/repository.js +1969 -0
  310. package/src/cli/run.js +3326 -0
  311. package/src/cli/secrets.js +151 -0
  312. package/src/cli/ssh.js +975 -0
  313. package/src/cli/static.js +653 -0
  314. package/src/cli/system.js +332 -0
  315. package/src/cli/test.js +176 -0
  316. package/src/client/Cryptokoyn.index.js +30 -0
  317. package/src/client/CyberiaPortal.index.js +31 -0
  318. package/src/client/Default.index.js +77 -0
  319. package/src/client/Itemledger.index.js +35 -0
  320. package/src/client/Underpost.index.js +31 -0
  321. package/src/client/components/core/404.js +20 -0
  322. package/src/client/components/core/500.js +20 -0
  323. package/src/client/components/core/Account.js +630 -0
  324. package/src/client/components/core/AgGrid.js +238 -0
  325. package/src/client/components/core/Alert.js +76 -0
  326. package/src/client/components/core/AppStore.js +69 -0
  327. package/src/client/components/core/Auth.js +353 -0
  328. package/src/client/components/core/Badge.js +26 -0
  329. package/src/client/components/core/Blockchain.js +41 -0
  330. package/src/client/components/core/Blog.js +9 -0
  331. package/src/client/components/core/BtnIcon.js +109 -0
  332. package/src/client/components/core/CalendarCore.js +437 -0
  333. package/src/client/components/core/Chat.js +62 -0
  334. package/src/client/components/core/ClientEvents.js +163 -0
  335. package/src/client/components/core/ColorPaletteElement.js +309 -0
  336. package/src/client/components/core/CommonJs.js +1014 -0
  337. package/src/client/components/core/Content.js +349 -0
  338. package/src/client/components/core/Css.js +1134 -0
  339. package/src/client/components/core/CssCore.js +881 -0
  340. package/src/client/components/core/D3Chart.js +44 -0
  341. package/src/client/components/core/Docs.js +478 -0
  342. package/src/client/components/core/DropDown.js +321 -0
  343. package/src/client/components/core/EventBus.js +96 -0
  344. package/src/client/components/core/EventsUI.js +130 -0
  345. package/src/client/components/core/FileExplorer.js +1406 -0
  346. package/src/client/components/core/FullScreen.js +201 -0
  347. package/src/client/components/core/Input.js +537 -0
  348. package/src/client/components/core/Keyboard.js +80 -0
  349. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  350. package/src/client/components/core/LoadingAnimation.js +152 -0
  351. package/src/client/components/core/LogIn.js +212 -0
  352. package/src/client/components/core/LogOut.js +72 -0
  353. package/src/client/components/core/Logger.js +22 -0
  354. package/src/client/components/core/Modal.js +2956 -0
  355. package/src/client/components/core/NotificationManager.js +80 -0
  356. package/src/client/components/core/Pagination.js +252 -0
  357. package/src/client/components/core/Panel.js +1308 -0
  358. package/src/client/components/core/PanelForm.js +915 -0
  359. package/src/client/components/core/Polyhedron.js +947 -0
  360. package/src/client/components/core/PublicProfile.js +895 -0
  361. package/src/client/components/core/Recover.js +211 -0
  362. package/src/client/components/core/Responsive.js +146 -0
  363. package/src/client/components/core/RichText.js +33 -0
  364. package/src/client/components/core/Router.js +523 -0
  365. package/src/client/components/core/Scroll.js +76 -0
  366. package/src/client/components/core/SearchBox.js +1007 -0
  367. package/src/client/components/core/SignUp.js +153 -0
  368. package/src/client/components/core/SocketIo.js +163 -0
  369. package/src/client/components/core/SocketIoHandler.js +75 -0
  370. package/src/client/components/core/Stream.js +161 -0
  371. package/src/client/components/core/ToggleSwitch.js +89 -0
  372. package/src/client/components/core/ToolTip.js +78 -0
  373. package/src/client/components/core/Translate.js +694 -0
  374. package/src/client/components/core/Validator.js +140 -0
  375. package/src/client/components/core/VanillaJs.js +485 -0
  376. package/src/client/components/core/Wallet.js +95 -0
  377. package/src/client/components/core/WebComponent.js +44 -0
  378. package/src/client/components/core/Webhook.js +58 -0
  379. package/src/client/components/core/Worker.js +313 -0
  380. package/src/client/components/core/windowGetDimensions.js +269 -0
  381. package/src/client/components/cryptokoyn/AppShellCryptokoyn.js +352 -0
  382. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  383. package/src/client/components/cryptokoyn/CssCryptokoyn.js +212 -0
  384. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +16 -0
  385. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +12 -0
  386. package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
  387. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +16 -0
  388. package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +11 -0
  389. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +6 -0
  390. package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
  391. package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
  392. package/src/client/components/cyberia/InstanceEngineCyberia.js +1088 -0
  393. package/src/client/components/cyberia/InstanceSelectionView.js +900 -0
  394. package/src/client/components/cyberia/MapEngineCyberia.js +1976 -0
  395. package/src/client/components/cyberia/ObjectLayerEngine.js +1540 -0
  396. package/src/client/components/cyberia/ObjectLayerEngineModal.js +2420 -0
  397. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +1522 -0
  398. package/src/client/components/cyberia/SharedDefaultsCyberia.js +528 -0
  399. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +772 -0
  400. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  401. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +254 -0
  402. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +21 -0
  403. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +16 -0
  404. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +518 -0
  405. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +72 -0
  406. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +16 -0
  407. package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +13 -0
  408. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +6 -0
  409. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +48 -0
  410. package/src/client/components/default/AppShellDefault.js +765 -0
  411. package/src/client/components/default/AppStoreDefault.js +5 -0
  412. package/src/client/components/default/CommonDefault.js +29 -0
  413. package/src/client/components/default/CssDefault.js +27 -0
  414. package/src/client/components/default/LogInDefault.js +16 -0
  415. package/src/client/components/default/LogOutDefault.js +12 -0
  416. package/src/client/components/default/RouterDefault.js +47 -0
  417. package/src/client/components/default/SettingsDefault.js +16 -0
  418. package/src/client/components/default/SignUpDefault.js +11 -0
  419. package/src/client/components/default/SocketIoDefault.js +6 -0
  420. package/src/client/components/default/TranslateDefault.js +7 -0
  421. package/src/client/components/itemledger/AppShellItemledger.js +353 -0
  422. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  423. package/src/client/components/itemledger/CssItemledger.js +212 -0
  424. package/src/client/components/itemledger/LogInItemledger.js +17 -0
  425. package/src/client/components/itemledger/LogOutItemledger.js +12 -0
  426. package/src/client/components/itemledger/RouterItemledger.js +38 -0
  427. package/src/client/components/itemledger/SettingsItemledger.js +16 -0
  428. package/src/client/components/itemledger/SignUpItemledger.js +11 -0
  429. package/src/client/components/itemledger/SocketIoItemledger.js +6 -0
  430. package/src/client/components/itemledger/TranslateItemledger.js +7 -0
  431. package/src/client/components/underpost/AppShellUnderpost.js +691 -0
  432. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  433. package/src/client/components/underpost/CssUnderpost.js +281 -0
  434. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
  435. package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
  436. package/src/client/components/underpost/LabGalleryUnderpost.js +79 -0
  437. package/src/client/components/underpost/LogInUnderpost.js +25 -0
  438. package/src/client/components/underpost/LogOutUnderpost.js +17 -0
  439. package/src/client/components/underpost/RouterUnderpost.js +45 -0
  440. package/src/client/components/underpost/SettingsUnderpost.js +16 -0
  441. package/src/client/components/underpost/SignUpUnderpost.js +11 -0
  442. package/src/client/components/underpost/SocketIoUnderpost.js +6 -0
  443. package/src/client/components/underpost/TranslateUnderpost.js +10 -0
  444. package/src/client/public/cryptokoyn/assets/banner/koyn-social.png +0 -0
  445. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  446. package/src/client/public/cryptokoyn/assets/logo/cryptokoyn.png +0 -0
  447. package/src/client/public/cryptokoyn/assets/splash/android-chrome-144x144.png +0 -0
  448. package/src/client/public/cryptokoyn/assets/splash/android-chrome-192x192.png +0 -0
  449. package/src/client/public/cryptokoyn/assets/splash/android-chrome-256x256.png +0 -0
  450. package/src/client/public/cryptokoyn/assets/splash/android-chrome-36x36.png +0 -0
  451. package/src/client/public/cryptokoyn/assets/splash/android-chrome-48x48.png +0 -0
  452. package/src/client/public/cryptokoyn/assets/splash/android-chrome-72x72.png +0 -0
  453. package/src/client/public/cryptokoyn/assets/splash/android-chrome-96x96.png +0 -0
  454. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114-precomposed.png +0 -0
  455. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114.png +0 -0
  456. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120-precomposed.png +0 -0
  457. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120.png +0 -0
  458. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144-precomposed.png +0 -0
  459. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144.png +0 -0
  460. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152-precomposed.png +0 -0
  461. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152.png +0 -0
  462. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180-precomposed.png +0 -0
  463. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180.png +0 -0
  464. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57-precomposed.png +0 -0
  465. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57.png +0 -0
  466. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60-precomposed.png +0 -0
  467. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60.png +0 -0
  468. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72-precomposed.png +0 -0
  469. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72.png +0 -0
  470. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76-precomposed.png +0 -0
  471. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76.png +0 -0
  472. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-precomposed.png +0 -0
  473. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon.png +0 -0
  474. package/src/client/public/cryptokoyn/assets/splash/favicon-16x16.png +0 -0
  475. package/src/client/public/cryptokoyn/assets/splash/favicon-32x32.png +0 -0
  476. package/src/client/public/cryptokoyn/assets/splash/mstile-144x144.png +0 -0
  477. package/src/client/public/cryptokoyn/assets/splash/mstile-150x150.png +0 -0
  478. package/src/client/public/cryptokoyn/assets/splash/mstile-310x150.png +0 -0
  479. package/src/client/public/cryptokoyn/assets/splash/mstile-310x310.png +0 -0
  480. package/src/client/public/cryptokoyn/assets/splash/mstile-70x70.png +0 -0
  481. package/src/client/public/cryptokoyn/assets/splash/safari-pinned-tab.svg +42 -0
  482. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  483. package/src/client/public/cryptokoyn/favicon.ico +0 -0
  484. package/src/client/public/cryptokoyn/microdata.json +85 -0
  485. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  486. package/src/client/public/cryptokoyn/sitemap +148 -0
  487. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +307 -0
  488. package/src/client/public/cyberia-docs/ARCHITECTURE.md +309 -0
  489. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +204 -0
  490. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +341 -0
  491. package/src/client/public/cyberia-docs/CYBERIA-LORE.md +84 -0
  492. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
  493. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +294 -0
  494. package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
  495. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +242 -0
  496. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
  497. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +309 -0
  498. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +228 -0
  499. package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
  500. package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
  501. package/src/client/public/cyberia-docs/WHITE-PAPER.md +740 -0
  502. package/src/client/public/default/android-chrome-144x144.png +0 -0
  503. package/src/client/public/default/android-chrome-192x192.png +0 -0
  504. package/src/client/public/default/android-chrome-256x256.png +0 -0
  505. package/src/client/public/default/android-chrome-36x36.png +0 -0
  506. package/src/client/public/default/android-chrome-384x384.png +0 -0
  507. package/src/client/public/default/android-chrome-48x48.png +0 -0
  508. package/src/client/public/default/android-chrome-512x512.png +0 -0
  509. package/src/client/public/default/android-chrome-72x72.png +0 -0
  510. package/src/client/public/default/android-chrome-96x96.png +0 -0
  511. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  512. package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
  513. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  514. package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
  515. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  516. package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
  517. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  518. package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
  519. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  520. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  521. package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
  522. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  523. package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
  524. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  525. package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
  526. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  527. package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
  528. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  529. package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
  530. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  531. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  532. package/src/client/public/default/apple-touch-icon.png +0 -0
  533. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  534. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  535. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  536. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  537. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  538. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  539. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  540. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  541. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  542. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  543. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  544. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  545. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  546. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  547. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  548. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  549. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  550. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  551. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  552. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  553. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  554. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  555. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  556. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  557. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  558. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  559. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  560. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  561. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  562. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  563. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  564. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  565. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  566. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  567. package/src/client/public/default/assets/background/dark.jpg +0 -0
  568. package/src/client/public/default/assets/background/dark.svg +557 -0
  569. package/src/client/public/default/assets/background/white.jpg +0 -0
  570. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  571. package/src/client/public/default/assets/background/white0.jpg +0 -0
  572. package/src/client/public/default/assets/logo/base-icon.png +0 -0
  573. package/src/client/public/default/assets/logo/underpost.gif +0 -0
  574. package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
  575. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  576. package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
  577. package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
  578. package/src/client/public/default/browserconfig.xml +12 -0
  579. package/src/client/public/default/favicon-16x16.png +0 -0
  580. package/src/client/public/default/favicon-32x32.png +0 -0
  581. package/src/client/public/default/favicon-48x48.png +0 -0
  582. package/src/client/public/default/favicon.ico +0 -0
  583. package/src/client/public/default/manifest.webmanifest +69 -0
  584. package/src/client/public/default/mstile-144x144.png +0 -0
  585. package/src/client/public/default/mstile-150x150.png +0 -0
  586. package/src/client/public/default/mstile-310x150.png +0 -0
  587. package/src/client/public/default/mstile-310x310.png +0 -0
  588. package/src/client/public/default/mstile-70x70.png +0 -0
  589. package/src/client/public/default/safari-pinned-tab.svg +24 -0
  590. package/src/client/public/default/site.webmanifest +69 -0
  591. package/src/client/public/default/sitemap +148 -0
  592. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  593. package/src/client/public/default/yandex-browser-manifest.json +9 -0
  594. package/src/client/public/doc/favicon.ico +0 -0
  595. package/src/client/public/doc/sitemap +148 -0
  596. package/src/client/public/itemledger/android-chrome-144x144.png +0 -0
  597. package/src/client/public/itemledger/android-chrome-192x192.png +0 -0
  598. package/src/client/public/itemledger/android-chrome-256x256.png +0 -0
  599. package/src/client/public/itemledger/android-chrome-36x36.png +0 -0
  600. package/src/client/public/itemledger/android-chrome-384x384.png +0 -0
  601. package/src/client/public/itemledger/android-chrome-48x48.png +0 -0
  602. package/src/client/public/itemledger/android-chrome-512x512.png +0 -0
  603. package/src/client/public/itemledger/android-chrome-72x72.png +0 -0
  604. package/src/client/public/itemledger/android-chrome-96x96.png +0 -0
  605. package/src/client/public/itemledger/apple-touch-icon-1024x1024.png +0 -0
  606. package/src/client/public/itemledger/apple-touch-icon-114x114.png +0 -0
  607. package/src/client/public/itemledger/apple-touch-icon-120x120.png +0 -0
  608. package/src/client/public/itemledger/apple-touch-icon-144x144.png +0 -0
  609. package/src/client/public/itemledger/apple-touch-icon-152x152.png +0 -0
  610. package/src/client/public/itemledger/apple-touch-icon-167x167.png +0 -0
  611. package/src/client/public/itemledger/apple-touch-icon-180x180.png +0 -0
  612. package/src/client/public/itemledger/apple-touch-icon-57x57.png +0 -0
  613. package/src/client/public/itemledger/apple-touch-icon-60x60.png +0 -0
  614. package/src/client/public/itemledger/apple-touch-icon-72x72.png +0 -0
  615. package/src/client/public/itemledger/apple-touch-icon-76x76.png +0 -0
  616. package/src/client/public/itemledger/apple-touch-icon-precomposed.png +0 -0
  617. package/src/client/public/itemledger/apple-touch-icon.png +0 -0
  618. package/src/client/public/itemledger/apple-touch-startup-image-1125x2436.png +0 -0
  619. package/src/client/public/itemledger/apple-touch-startup-image-1136x640.png +0 -0
  620. package/src/client/public/itemledger/apple-touch-startup-image-1170x2532.png +0 -0
  621. package/src/client/public/itemledger/apple-touch-startup-image-1179x2556.png +0 -0
  622. package/src/client/public/itemledger/apple-touch-startup-image-1242x2208.png +0 -0
  623. package/src/client/public/itemledger/apple-touch-startup-image-1242x2688.png +0 -0
  624. package/src/client/public/itemledger/apple-touch-startup-image-1284x2778.png +0 -0
  625. package/src/client/public/itemledger/apple-touch-startup-image-1290x2796.png +0 -0
  626. package/src/client/public/itemledger/apple-touch-startup-image-1334x750.png +0 -0
  627. package/src/client/public/itemledger/apple-touch-startup-image-1488x2266.png +0 -0
  628. package/src/client/public/itemledger/apple-touch-startup-image-1536x2048.png +0 -0
  629. package/src/client/public/itemledger/apple-touch-startup-image-1620x2160.png +0 -0
  630. package/src/client/public/itemledger/apple-touch-startup-image-1640x2160.png +0 -0
  631. package/src/client/public/itemledger/apple-touch-startup-image-1668x2224.png +0 -0
  632. package/src/client/public/itemledger/apple-touch-startup-image-1668x2388.png +0 -0
  633. package/src/client/public/itemledger/apple-touch-startup-image-1792x828.png +0 -0
  634. package/src/client/public/itemledger/apple-touch-startup-image-2048x1536.png +0 -0
  635. package/src/client/public/itemledger/apple-touch-startup-image-2048x2732.png +0 -0
  636. package/src/client/public/itemledger/apple-touch-startup-image-2160x1620.png +0 -0
  637. package/src/client/public/itemledger/apple-touch-startup-image-2160x1640.png +0 -0
  638. package/src/client/public/itemledger/apple-touch-startup-image-2208x1242.png +0 -0
  639. package/src/client/public/itemledger/apple-touch-startup-image-2224x1668.png +0 -0
  640. package/src/client/public/itemledger/apple-touch-startup-image-2266x1488.png +0 -0
  641. package/src/client/public/itemledger/apple-touch-startup-image-2388x1668.png +0 -0
  642. package/src/client/public/itemledger/apple-touch-startup-image-2436x1125.png +0 -0
  643. package/src/client/public/itemledger/apple-touch-startup-image-2532x1170.png +0 -0
  644. package/src/client/public/itemledger/apple-touch-startup-image-2556x1179.png +0 -0
  645. package/src/client/public/itemledger/apple-touch-startup-image-2688x1242.png +0 -0
  646. package/src/client/public/itemledger/apple-touch-startup-image-2732x2048.png +0 -0
  647. package/src/client/public/itemledger/apple-touch-startup-image-2778x1284.png +0 -0
  648. package/src/client/public/itemledger/apple-touch-startup-image-2796x1290.png +0 -0
  649. package/src/client/public/itemledger/apple-touch-startup-image-640x1136.png +0 -0
  650. package/src/client/public/itemledger/apple-touch-startup-image-750x1334.png +0 -0
  651. package/src/client/public/itemledger/apple-touch-startup-image-828x1792.png +0 -0
  652. package/src/client/public/itemledger/assets/logo/base-icon.png +0 -0
  653. package/src/client/public/itemledger/browserconfig.xml +12 -0
  654. package/src/client/public/itemledger/favicon-16x16.png +0 -0
  655. package/src/client/public/itemledger/favicon-32x32.png +0 -0
  656. package/src/client/public/itemledger/favicon-48x48.png +0 -0
  657. package/src/client/public/itemledger/favicon.ico +0 -0
  658. package/src/client/public/itemledger/manifest.webmanifest +69 -0
  659. package/src/client/public/itemledger/microdata.json +71 -0
  660. package/src/client/public/itemledger/mstile-144x144.png +0 -0
  661. package/src/client/public/itemledger/mstile-150x150.png +0 -0
  662. package/src/client/public/itemledger/mstile-310x150.png +0 -0
  663. package/src/client/public/itemledger/mstile-310x310.png +0 -0
  664. package/src/client/public/itemledger/mstile-70x70.png +0 -0
  665. package/src/client/public/itemledger/sitemap +148 -0
  666. package/src/client/public/itemledger/yandex-browser-50x50.png +0 -0
  667. package/src/client/public/itemledger/yandex-browser-manifest.json +9 -0
  668. package/src/client/public/test/favicon.ico +0 -0
  669. package/src/client/public/test/sitemap +148 -0
  670. package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +137 -0
  671. package/src/client/services/core/core.service.js +309 -0
  672. package/src/client/services/crypto/crypto.service.js +68 -0
  673. package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
  674. package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
  675. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
  676. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  677. package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
  678. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
  679. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  680. package/src/client/services/cyberia-instance/cyberia-instance.service.js +137 -0
  681. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
  682. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  683. package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
  684. package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
  685. package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
  686. package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
  687. package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
  688. package/src/client/services/default/default.management.js +1015 -0
  689. package/src/client/services/default/default.service.js +99 -0
  690. package/src/client/services/document/document.service.js +134 -0
  691. package/src/client/services/file/file.service.js +94 -0
  692. package/src/client/services/instance/instance.management.js +78 -0
  693. package/src/client/services/instance/instance.service.js +107 -0
  694. package/src/client/services/ipfs/ipfs.service.js +118 -0
  695. package/src/client/services/object-layer/object-layer.management.js +414 -0
  696. package/src/client/services/object-layer/object-layer.service.js +208 -0
  697. package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +99 -0
  698. package/src/client/services/test/test.service.js +68 -0
  699. package/src/client/services/user/guest.service.js +86 -0
  700. package/src/client/services/user/user.management.js +51 -0
  701. package/src/client/services/user/user.service.js +106 -0
  702. package/src/client/ssr/RootDocument.js +237 -0
  703. package/src/client/ssr/body/404.js +77 -0
  704. package/src/client/ssr/body/500.js +76 -0
  705. package/src/client/ssr/body/CacheControl.js +117 -0
  706. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +97 -0
  707. package/src/client/ssr/body/DefaultSplashScreen.js +97 -0
  708. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  709. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +90 -0
  710. package/src/client/ssr/head/CryptokoynScripts.js +4 -0
  711. package/src/client/ssr/head/Css.js +241 -0
  712. package/src/client/ssr/head/CyberiaPortalScripts.js +6 -0
  713. package/src/client/ssr/head/DefaultScripts.js +6 -0
  714. package/src/client/ssr/head/ItemledgerScripts.js +4 -0
  715. package/src/client/ssr/head/Microdata.js +11 -0
  716. package/src/client/ssr/head/Production.js +1 -0
  717. package/src/client/ssr/head/Pwa.js +146 -0
  718. package/src/client/ssr/head/PwaItemledger.js +197 -0
  719. package/src/client/ssr/head/Seo.js +15 -0
  720. package/src/client/ssr/head/UnderpostScripts.js +6 -0
  721. package/src/client/ssr/mailer/DefaultRecoverEmail.js +20 -0
  722. package/src/client/ssr/mailer/DefaultVerifyEmail.js +16 -0
  723. package/src/client/ssr/views/Cyberia404.js +328 -0
  724. package/src/client/ssr/views/CyberiaServerMetrics.js +1070 -0
  725. package/src/client/ssr/views/Maintenance.js +64 -0
  726. package/src/client/ssr/views/NoNetworkConnection.js +68 -0
  727. package/src/client/ssr/views/Test.js +199 -0
  728. package/src/client/sw/core.sw.js +274 -0
  729. package/src/client-builder/client-build-docs.js +493 -0
  730. package/src/client-builder/client-build-live.js +100 -0
  731. package/src/client-builder/client-build.js +1092 -0
  732. package/src/client-builder/client-dev-server.js +88 -0
  733. package/src/client-builder/client-formatted.js +170 -0
  734. package/src/client-builder/client-icons.js +108 -0
  735. package/src/client-builder/ssr.js +124 -0
  736. package/src/client.build.js +17 -0
  737. package/src/client.dev.js +21 -0
  738. package/src/db/DataBaseProvider.js +213 -0
  739. package/src/db/mariadb/MariaDB.js +72 -0
  740. package/src/db/mongo/MongoBootstrap.js +657 -0
  741. package/src/db/mongo/MongooseDB.js +199 -0
  742. package/src/grpc/cyberia/grpc-server.js +162 -0
  743. package/src/index.js +357 -0
  744. package/src/mailer/EmailRender.js +116 -0
  745. package/src/mailer/MailerProvider.js +213 -0
  746. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +413 -0
  747. package/src/projects/cyberia/besu-genesis-generator.js +1630 -0
  748. package/src/projects/cyberia/catalog-cyberia.js +90 -0
  749. package/src/projects/cyberia/gemini-client.js +175 -0
  750. package/src/projects/cyberia/generate-saga.js +2137 -0
  751. package/src/projects/cyberia/hot-reload-trigger.js +163 -0
  752. package/src/projects/cyberia/instance-data.js +719 -0
  753. package/src/projects/cyberia/ipfs-client.js +599 -0
  754. package/src/projects/cyberia/map-preview-generator.js +304 -0
  755. package/src/projects/cyberia/object-layer.js +978 -0
  756. package/src/projects/cyberia/semantic-layer-generator-floor.js +319 -0
  757. package/src/projects/cyberia/semantic-layer-generator-resource.js +259 -0
  758. package/src/projects/cyberia/semantic-layer-generator-skin.js +1164 -0
  759. package/src/projects/cyberia/semantic-layer-generator.js +753 -0
  760. package/src/projects/cyberia/shape-generator.js +1060 -0
  761. package/src/projects/underpost/catalog-underpost.js +60 -0
  762. package/src/proxy.js +19 -0
  763. package/src/runtime/cyberia-client/Dockerfile +49 -0
  764. package/src/runtime/cyberia-client/Dockerfile.dev +75 -0
  765. package/src/runtime/cyberia-server/Dockerfile +43 -0
  766. package/src/runtime/cyberia-server/Dockerfile.dev +56 -0
  767. package/src/runtime/engine-cyberia/Dockerfile +161 -0
  768. package/src/runtime/engine-cyberia/Dockerfile.dev +161 -0
  769. package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
  770. package/src/runtime/engine-cyberia/compose.env +144 -0
  771. package/src/runtime/engine-cyberia/docker-compose.yml +434 -0
  772. package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
  773. package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
  774. package/src/runtime/engine-cyberia/nginx.conf +128 -0
  775. package/src/runtime/express/Dockerfile +45 -0
  776. package/src/runtime/express/Express.js +285 -0
  777. package/src/runtime/lampp/Dockerfile +62 -0
  778. package/src/runtime/lampp/Lampp.js +359 -0
  779. package/src/runtime/nginx/Nginx.js +250 -0
  780. package/src/runtime/wp/Dockerfile +62 -0
  781. package/src/runtime/wp/Wp.js +642 -0
  782. package/src/server/auth.js +713 -0
  783. package/src/server/backup.js +102 -0
  784. package/src/server/catalog.js +72 -0
  785. package/src/server/conf.js +2316 -0
  786. package/src/server/cron.js +476 -0
  787. package/src/server/crypto.js +210 -0
  788. package/src/server/data-query.js +461 -0
  789. package/src/server/dns.js +553 -0
  790. package/src/server/downloader.js +73 -0
  791. package/src/server/logger.js +229 -0
  792. package/src/server/middlewares.js +152 -0
  793. package/src/server/peer.js +75 -0
  794. package/src/server/process.js +299 -0
  795. package/src/server/proxy.js +139 -0
  796. package/src/server/runtime-status.js +252 -0
  797. package/src/server/runtime.js +183 -0
  798. package/src/server/start.js +272 -0
  799. package/src/server/tls.js +254 -0
  800. package/src/server/valkey.js +201 -0
  801. package/src/server.js +25 -0
  802. package/src/ws/IoInterface.js +129 -0
  803. package/src/ws/IoServer.js +68 -0
  804. package/src/ws/core/channels/core.ws.chat.js +68 -0
  805. package/src/ws/core/channels/core.ws.mailer.js +116 -0
  806. package/src/ws/core/channels/core.ws.stream.js +90 -0
  807. package/src/ws/core/core.ws.connection.js +41 -0
  808. package/src/ws/core/core.ws.emit.js +37 -0
  809. package/src/ws/core/core.ws.server.js +44 -0
  810. package/src/ws/default/channels/default.ws.main.js +57 -0
  811. package/src/ws/default/default.ws.connection.js +35 -0
  812. package/src/ws/default/default.ws.emit.js +14 -0
  813. package/src/ws/default/default.ws.server.js +39 -0
  814. package/test/api.test.js +53 -0
  815. package/test/crypto.test.js +117 -0
  816. package/test/cyberia-instance-conf-defaults.test.js +140 -0
  817. package/test/deploy-monitor.test.js +267 -0
  818. package/test/shape-generator.test.js +463 -0
  819. package/tsconfig.docs.json +15 -0
  820. package/typedoc.dd-cyberia.json +31 -0
  821. package/typedoc.json +31 -0
package/src/cli/ssh.js ADDED
@@ -0,0 +1,975 @@
1
+ /**
2
+ * SSH module for managing SSH key generation and connection setup.
3
+ * @module src/cli/ssh.js
4
+ * @namespace UnderpostSSH
5
+ */
6
+
7
+ import { generateRandomPasswordSelection } from '../client/components/core/CommonJs.js';
8
+ import { pbcopy, shellExec } from '../server/process.js';
9
+ import { loggerFactory } from '../server/logger.js';
10
+ import fs from 'fs-extra';
11
+ import Underpost from '../index.js';
12
+
13
+ const logger = loggerFactory(import.meta);
14
+
15
+ /**
16
+ * @class UnderpostSSH
17
+ * @description Manages SSH key generation and connection setup.
18
+ * @memberof UnderpostSSH
19
+ */
20
+ class UnderpostSSH {
21
+ static API = {
22
+ /**
23
+ * Loads configuration node from disk or returns default empty config.
24
+ * @method
25
+ * @function loadConfigNode
26
+ * @memberof UnderpostSSH
27
+ * @param {string} deployId - Deployment ID for the config path
28
+ * @returns {{confNode: Object, confNodePath: string}} Configuration node and its file path
29
+ * @description Loads or creates a config node with users object structure
30
+ */
31
+ loadConfigNode: (deployId) => {
32
+ const confNodePath = `./engine-private/conf/${deployId}/conf.node.json`;
33
+ const confNode = fs.existsSync(confNodePath) ? JSON.parse(fs.readFileSync(confNodePath, 'utf8')) : { users: {} };
34
+ return { confNode, confNodePath };
35
+ },
36
+
37
+ /**
38
+ * Saves configuration node to disk.
39
+ * @method
40
+ * @function saveConfigNode
41
+ * @memberof UnderpostSSH
42
+ * @param {string} confNodePath - Path to the configuration file
43
+ * @param {Object} confNode - Configuration object to save
44
+ * @returns {void}
45
+ */
46
+ saveConfigNode: (confNodePath, confNode) => {
47
+ fs.outputFileSync(confNodePath, JSON.stringify(confNode, null, 4), 'utf8');
48
+ },
49
+
50
+ /**
51
+ * Checks if a system user exists.
52
+ * @method
53
+ * @function checkUserExists
54
+ * @memberof UnderpostSSH
55
+ * @param {string} username - Username to check
56
+ * @returns {boolean} True if user exists, false otherwise
57
+ */
58
+ checkUserExists: (username) => {
59
+ const result = shellExec(`id -u ${username} 2>/dev/null || echo "not_found"`, {
60
+ silent: true,
61
+ stdout: true,
62
+ }).trim();
63
+ return result !== 'not_found';
64
+ },
65
+
66
+ /**
67
+ * Gets the home directory for a given user.
68
+ * @method
69
+ * @function getUserHome
70
+ * @memberof UnderpostSSH
71
+ * @param {string} username - Username to get home directory for
72
+ * @returns {string} User's home directory path
73
+ */
74
+ getUserHome: (username) => {
75
+ return shellExec(`getent passwd ${username} | cut -d: -f6`, {
76
+ silent: true,
77
+ stdout: true,
78
+ }).trim();
79
+ },
80
+
81
+ /**
82
+ * Creates a system user with password and groups.
83
+ * @method
84
+ * @function createSystemUser
85
+ * @memberof UnderpostSSH
86
+ * @param {string} username - Username to create
87
+ * @param {string} password - Password for the user
88
+ * @param {string} groups - Comma-separated list of groups
89
+ * @returns {void}
90
+ */
91
+ createSystemUser: (username, password, groups) => {
92
+ shellExec(`useradd -m -s /bin/bash ${username}`);
93
+ shellExec(`echo "${username}:${password}" | chpasswd`);
94
+ if (groups) {
95
+ for (const group of groups.split(',').map((g) => g.trim())) {
96
+ shellExec(`usermod -aG "${group}" "${username}"`);
97
+ }
98
+ }
99
+ },
100
+
101
+ /**
102
+ * Ensures SSH directory exists with proper permissions.
103
+ * @method
104
+ * @function ensureSSHDirectory
105
+ * @memberof UnderpostSSH
106
+ * @param {string} sshDir - Path to SSH directory
107
+ * @returns {void}
108
+ */
109
+ ensureSSHDirectory: (sshDir) => {
110
+ if (!fs.existsSync(sshDir)) {
111
+ shellExec(`mkdir -p ${sshDir}`);
112
+ shellExec(`chmod 700 ${sshDir}`);
113
+ }
114
+ },
115
+
116
+ /**
117
+ * Sets proper permissions on SSH files.
118
+ * @method
119
+ * @function setSSHFilePermissions
120
+ * @memberof UnderpostSSH
121
+ * @param {string} sshDir - SSH directory path
122
+ * @param {string} username - Username for ownership
123
+ * @param {string} [keyPath] - Optional private key path
124
+ * @param {string} [pubKeyPath] - Optional public key path
125
+ * @returns {void}
126
+ */
127
+ setSSHFilePermissions: (sshDir, username, keyPath, pubKeyPath) => {
128
+ shellExec(`chmod 600 ${sshDir}/authorized_keys`);
129
+ shellExec(`chmod 644 ${sshDir}/known_hosts`);
130
+ if (keyPath) shellExec(`chmod 600 ${keyPath}`);
131
+ if (pubKeyPath) shellExec(`chmod 644 ${pubKeyPath}`);
132
+ shellExec(`chown -R ${username}:${username} ${sshDir}`);
133
+ },
134
+
135
+ /**
136
+ * Configures authorized_keys for a user.
137
+ * @method
138
+ * @function configureAuthorizedKeys
139
+ * @memberof UnderpostSSH
140
+ * @param {string} sshDir - SSH directory path
141
+ * @param {string} pubKeyPath - Public key file path
142
+ * @param {boolean} disablePassword - Whether to add no-forwarding restrictions
143
+ * @returns {void}
144
+ */
145
+ configureAuthorizedKeys: (sshDir, pubKeyPath, disablePassword) => {
146
+ if (disablePassword) {
147
+ shellExec(`cat >> ${sshDir}/authorized_keys <<EOF
148
+ no-port-forwarding,no-X11-forwarding,no-agent-forwarding ${fs.readFileSync(pubKeyPath, 'utf8')}
149
+ EOF`);
150
+ } else {
151
+ shellExec(`cat ${pubKeyPath} >> ${sshDir}/authorized_keys`);
152
+ }
153
+ },
154
+
155
+ /**
156
+ * Configures known_hosts with SSH server keys.
157
+ * @method
158
+ * @function configureKnownHosts
159
+ * @memberof UnderpostSSH
160
+ * @param {string} sshDir - SSH directory path
161
+ * @param {number} port - SSH port number
162
+ * @param {string} [host] - Optional external host to add
163
+ * @returns {void}
164
+ */
165
+ configureKnownHosts: (sshDir, port, host) => {
166
+ shellExec(`ssh-keyscan -p ${port} -H localhost >> ${sshDir}/known_hosts`);
167
+ shellExec(`ssh-keyscan -p ${port} -H 127.0.0.1 >> ${sshDir}/known_hosts`);
168
+ if (host) shellExec(`ssh-keyscan -p ${port} -H ${host} >> ${sshDir}/known_hosts`);
169
+ },
170
+
171
+ /**
172
+ * Configures sudoers for passwordless sudo or sets user password.
173
+ * @method
174
+ * @function configureSudoAccess
175
+ * @memberof UnderpostSSH
176
+ * @param {string} username - Username to configure
177
+ * @param {string} password - User password
178
+ * @param {boolean} disablePassword - Whether to enable passwordless sudo
179
+ * @returns {void}
180
+ */
181
+ configureSudoAccess: (username, password, disablePassword) => {
182
+ if (disablePassword) {
183
+ shellExec(`echo '${username} ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/90_${username}`);
184
+ } else {
185
+ shellExec(`echo "${username}:${password}" | sudo chpasswd`);
186
+ }
187
+ },
188
+
189
+ /**
190
+ * Main callback function for SSH operations including user management, key import/export, and SSH service configuration.
191
+ * @async
192
+ * @function callback
193
+ * @memberof UnderpostSSH
194
+ * @param {Object} options - Configuration options for SSH operations
195
+ * @param {string} [options.deployId=''] - Deployment ID context for SSH operations
196
+ * @param {boolean} [options.generate=false] - Generate new SSH credentials
197
+ * @param {string} [options.user=''] - SSH user name (defaults to 'root')
198
+ * @param {string} [options.password=''] - SSH user password (auto-generated if not provided, overridden by saved config if user exists)
199
+ * @param {string} [options.host=''] - SSH host address (defaults to public IP, overridden by saved config if user exists)
200
+ * @param {string} [options.filter=''] - Filter for user/group listings
201
+ * @param {string} [options.groups=''] - Comma-separated list of groups for the user (defaults to 'wheel')
202
+ * @param {number} [options.port=22] - SSH port number
203
+ * @param {boolean} [options.start=false] - Start SSH service with hardened configuration
204
+ * @param {boolean} [options.userAdd=false] - Add a new SSH user and generate keys
205
+ * @param {boolean} [options.userRemove=false] - Remove an SSH user and cleanup keys
206
+ * @param {boolean} [options.userLs=false] - List all SSH users and groups
207
+ * @param {boolean} [options.reset=false] - Reset SSH configuration (clear authorized_keys and known_hosts)
208
+ * @param {boolean} [options.keysList=false] - List authorized SSH keys
209
+ * @param {boolean} [options.hostsList=false] - List known SSH hosts
210
+ * @param {boolean} [options.disablePassword=false] - If true, enable passwordless sudo and add SSH restrictions
211
+ * @param {boolean} [options.keyTest=false] - Test SSH key generation
212
+ * @param {boolean} [options.stop=false] - Stop SSH service
213
+ * @param {boolean} [options.status=false] - Check SSH service status
214
+ * @param {boolean} [options.connectUri=false] - Output SSH connection URI
215
+ * @param {boolean} [options.copy=false] - Copy SSH connection URI to clipboard
216
+ * @returns {Promise<void>}
217
+ * @description
218
+ * Handles various SSH operations:
219
+ * - User creation with automatic key generation and backup
220
+ * - User removal with key cleanup
221
+ * - Key import/export between SSH directory and private backup location
222
+ * - SSH service initialization and hardening
223
+ * - User and group listing with optional filtering
224
+ */
225
+ callback: async (
226
+ options = {
227
+ deployId: '',
228
+ generate: false,
229
+ user: '',
230
+ password: '',
231
+ host: '',
232
+ filter: '',
233
+ groups: '',
234
+ port: 22,
235
+ start: false,
236
+ userAdd: false,
237
+ userRemove: false,
238
+ userLs: false,
239
+ reset: false,
240
+ keysList: false,
241
+ hostsList: false,
242
+ disablePassword: false,
243
+ keyTest: false,
244
+ stop: false,
245
+ status: false,
246
+ connectUri: false,
247
+ copy: false,
248
+ },
249
+ ) => {
250
+ let confNode, confNodePath;
251
+
252
+ // Set defaults
253
+ if (!options.user) options.user = 'root';
254
+ if (!options.host) options.host = await Underpost.dns.getPublicIp();
255
+ if (!options.password) options.password = options.disablePassword ? '' : generateRandomPasswordSelection(16);
256
+ if (!options.groups) options.groups = 'wheel';
257
+ if (!options.port) options.port = 22; // Handle connect uri
258
+
259
+ const userHome = Underpost.ssh.getUserHome(options.user);
260
+ options.userHome = userHome;
261
+
262
+ // Load config and override password and host if user exists in config
263
+ if (options.deployId) {
264
+ const config = Underpost.ssh.loadConfigNode(options.deployId);
265
+ confNode = config.confNode;
266
+ confNodePath = config.confNodePath;
267
+
268
+ if (confNode.users && confNode.users[options.user]) {
269
+ if (confNode.users[options.user].host) {
270
+ options.host = confNode.users[options.user].host;
271
+ logger.info(`Using saved host for user ${options.user}: ${options.host}`);
272
+ }
273
+ if (confNode.users[options.user].password === '') {
274
+ options.disablePassword = true;
275
+ options.password = '';
276
+ logger.info(`Using saved empty password for user ${options.user}`);
277
+ } else if (confNode.users[options.user].password) {
278
+ options.disablePassword = false;
279
+ options.password = confNode.users[options.user].password;
280
+ logger.info(`Using saved password for user ${options.user}`);
281
+ }
282
+ options.port = options.port || confNode.users[options.user].port || 22;
283
+ }
284
+ }
285
+
286
+ logger.info('options', options);
287
+
288
+ // Handle connect uri
289
+ if (options.connectUri) {
290
+ const keyPath = `${userHome}/.ssh/id_rsa`;
291
+ const uri = `ssh ${options.user}@${options.host} -i ${keyPath} -p ${options.port}`;
292
+ if (options.copy) {
293
+ pbcopy(uri);
294
+ } else console.log(uri);
295
+ return;
296
+ }
297
+
298
+ // Handle reset operation
299
+ if (options.reset) {
300
+ shellExec(`> ${userHome}/.ssh/authorized_keys`);
301
+ shellExec(`> ${userHome}/.ssh/known_hosts`);
302
+ }
303
+
304
+ if (options.userLs) {
305
+ const filter = options.filter ? `${options.filter}` : '';
306
+ const groupsOut = shellExec(`getent group${filter ? ` | grep '${filter}'` : ''}`, {
307
+ silent: true,
308
+ stdout: true,
309
+ });
310
+ const usersOut = shellExec(`getent passwd${filter ? ` | grep '${filter}'` : ''}`, {
311
+ silent: true,
312
+ stdout: true,
313
+ });
314
+ console.log('Groups'.bold.blue);
315
+ console.log(`group_name : password_x : GID(Internal Group ID) : user_list`.blue);
316
+ console.log(filter ? groupsOut.replaceAll(filter, filter.red) : groupsOut);
317
+ console.log('Users'.bold.blue);
318
+ console.log(`user : x : UID : GID : GECOS : home_dir : shell`.blue);
319
+ console.log(filter ? usersOut.replaceAll(filter, filter.red) : usersOut);
320
+ }
321
+
322
+ // Handle user removal (works with or without deployId)
323
+ if (options.userRemove) {
324
+ const groups = shellExec(`id -Gn ${options.user}`, { silent: true, stdout: true }).trim().replace(/ /g, ', ');
325
+ shellExec(`userdel -r ${options.user}`);
326
+
327
+ // Remove sudoers file if it exists
328
+ const sudoersFile = `/etc/sudoers.d/90_${options.user}`;
329
+ if (fs.existsSync(sudoersFile)) {
330
+ shellExec(`sudo rm -f ${sudoersFile}`);
331
+ logger.info(`Sudoers file removed: ${sudoersFile}`);
332
+ }
333
+
334
+ // Remove the private key copy folder and update config only if deployId is provided
335
+ if (options.deployId) {
336
+ if (!confNode) {
337
+ const config = Underpost.ssh.loadConfigNode(options.deployId);
338
+ confNode = config.confNode;
339
+ confNodePath = config.confNodePath;
340
+ }
341
+
342
+ const privateCopyDir = `./engine-private/conf/${options.deployId}/users/${options.user}`;
343
+ if (fs.existsSync(privateCopyDir)) {
344
+ fs.removeSync(privateCopyDir);
345
+ logger.info(`Private key copy removed from ${privateCopyDir}`);
346
+ }
347
+
348
+ delete confNode.users[options.user];
349
+ Underpost.ssh.saveConfigNode(confNodePath, confNode);
350
+ }
351
+
352
+ logger.info(`User removed`);
353
+ if (groups) logger.info(`User removed from groups: ${groups}`);
354
+ return;
355
+ }
356
+
357
+ // Handle user addition (works with or without deployId)
358
+ if (options.userAdd) {
359
+ let privateCopyDir, privateKeyPath, publicKeyPath, keysExistInBackup, userExistsInConfig;
360
+
361
+ // If deployId is provided, check for existing config and backup keys
362
+ if (options.deployId) {
363
+ if (!confNode) {
364
+ const config = Underpost.ssh.loadConfigNode(options.deployId);
365
+ confNode = config.confNode;
366
+ confNodePath = config.confNodePath;
367
+ }
368
+
369
+ userExistsInConfig = confNode.users && confNode.users[options.user];
370
+ privateCopyDir = `./engine-private/conf/${options.deployId}/users/${options.user}`;
371
+ privateKeyPath = `${privateCopyDir}/id_rsa`;
372
+ publicKeyPath = `${privateCopyDir}/id_rsa.pub`;
373
+ keysExistInBackup = fs.existsSync(privateKeyPath) && fs.existsSync(publicKeyPath);
374
+
375
+ // If user exists in config AND keys exist in backup, import those keys
376
+ if (userExistsInConfig && keysExistInBackup) {
377
+ logger.info(`User ${options.user} already exists in config. Importing existing keys...`);
378
+
379
+ // Create system user if it doesn't exist
380
+ const userExists = Underpost.ssh.checkUserExists(options.user);
381
+ if (!userExists) {
382
+ Underpost.ssh.createSystemUser(options.user, options.password, options.groups);
383
+ }
384
+
385
+ const userHome = Underpost.ssh.getUserHome(options.user);
386
+ const sshDir = `${userHome}/.ssh`;
387
+ Underpost.ssh.ensureSSHDirectory(sshDir);
388
+
389
+ const userKeyPath = `${sshDir}/id_rsa`;
390
+ const userPubKeyPath = `${sshDir}/id_rsa.pub`;
391
+
392
+ // Import keys from backup
393
+ fs.copyFileSync(privateKeyPath, userKeyPath);
394
+ fs.copyFileSync(publicKeyPath, userPubKeyPath);
395
+
396
+ Underpost.ssh.configureAuthorizedKeys(sshDir, userPubKeyPath, options.disablePassword);
397
+ Underpost.ssh.configureSudoAccess(options.user, options.password, options.disablePassword);
398
+ Underpost.ssh.configureKnownHosts(sshDir, options.port, options.host);
399
+ Underpost.ssh.setSSHFilePermissions(sshDir, options.user, userKeyPath, userPubKeyPath);
400
+
401
+ logger.info(`Keys imported from ${privateCopyDir} to ${sshDir}`);
402
+ logger.info(`User added with existing keys`);
403
+ return;
404
+ }
405
+ }
406
+
407
+ // New user or no existing keys - create new user and generate keys
408
+ Underpost.ssh.createSystemUser(options.user, options.password, options.groups);
409
+
410
+ const userHome = Underpost.ssh.getUserHome(options.user);
411
+ const sshDir = `${userHome}/.ssh`;
412
+ Underpost.ssh.ensureSSHDirectory(sshDir);
413
+
414
+ const keyPath = `${sshDir}/id_rsa`;
415
+ const pubKeyPath = `${sshDir}/id_rsa.pub`;
416
+
417
+ if (!fs.existsSync(keyPath)) {
418
+ shellExec(
419
+ `ssh-keygen -t ed25519 -f ${keyPath} -N "${options.password}" -q -C "${options.user}@${options.host}"`,
420
+ );
421
+ }
422
+
423
+ Underpost.ssh.configureAuthorizedKeys(sshDir, pubKeyPath, options.disablePassword);
424
+ Underpost.ssh.configureSudoAccess(options.user, options.password, options.disablePassword);
425
+ Underpost.ssh.configureKnownHosts(sshDir, options.port, options.host);
426
+ Underpost.ssh.setSSHFilePermissions(sshDir, options.user, keyPath, pubKeyPath);
427
+
428
+ // Save a copy of the keys to the private folder only if deployId is provided
429
+ if (options.deployId) {
430
+ if (!privateCopyDir) privateCopyDir = `./engine-private/conf/${options.deployId}/users/${options.user}`;
431
+ fs.ensureDirSync(privateCopyDir);
432
+
433
+ const privateKeyCopyPath = `${privateCopyDir}/id_rsa`;
434
+ const publicKeyCopyPath = `${privateCopyDir}/id_rsa.pub`;
435
+
436
+ fs.copyFileSync(keyPath, privateKeyCopyPath);
437
+ fs.copyFileSync(pubKeyPath, publicKeyCopyPath);
438
+
439
+ logger.info(`Keys backed up to ${privateCopyDir}`);
440
+
441
+ confNode.users[options.user] = {
442
+ ...confNode.users[options.user],
443
+ ...options,
444
+ keyPath,
445
+ pubKeyPath,
446
+ privateKeyCopyPath,
447
+ publicKeyCopyPath,
448
+ };
449
+ Underpost.ssh.saveConfigNode(confNodePath, confNode);
450
+ }
451
+
452
+ logger.info(`User added`);
453
+ return;
454
+ }
455
+
456
+ // Handle config user listing (only with deployId)
457
+ if (options.deployId) {
458
+ if (!confNode) {
459
+ const config = Underpost.ssh.loadConfigNode(options.deployId);
460
+ confNode = config.confNode;
461
+ confNodePath = config.confNodePath;
462
+ }
463
+
464
+ if (options.userLs && confNode && confNode.users) {
465
+ logger.info(`Users in config:`);
466
+ Object.keys(confNode.users).forEach((user) => {
467
+ logger.info(`- ${user}`);
468
+ });
469
+ }
470
+ }
471
+
472
+ // Handle generate root keys
473
+ if (options.generate)
474
+ Underpost.ssh.generateKeys({ user: options.user, password: options.password, host: options.host });
475
+
476
+ // Handle list operations
477
+ if (options.keysList) shellExec(`cat ${userHome}/.ssh/authorized_keys`);
478
+ if (options.hostsList) shellExec(`cat ${userHome}/.ssh/known_hosts`);
479
+
480
+ // Handle key test
481
+ if (options.keyTest) {
482
+ const keyPath = `${userHome}/.ssh/id_rsa`;
483
+ shellExec(`ssh-keygen -y -f ${keyPath} -P "${options.password}"`);
484
+ }
485
+
486
+ // Handle stop server
487
+ if (options.stop) shellExec('service sshd stop');
488
+
489
+ // Handle start server
490
+ if (options.start) {
491
+ Underpost.ssh.chmod({ user: options.user });
492
+ Underpost.ssh.initService({ port: options.port });
493
+ }
494
+
495
+ // Handle status server
496
+ if (options.status) shellExec('service sshd status');
497
+ },
498
+
499
+ /**
500
+ * Synchronously copies a local directory to a remote host over key-only SSH,
501
+ * streaming it as a tar archive (no intermediate file) and fixing ownership.
502
+ * Mirrors the kind-node `tar | docker cp` provisioning pattern but targets a
503
+ * real node via SSH, so node-local hostPath volumes can be materialized on the
504
+ * node where the pod will actually run.
505
+ *
506
+ * Idempotent and re-runnable: `mkdir -p` + `tar -x` overwrite in place. Throws
507
+ * on any SSH/tar failure so an empty-volume deploy is never produced silently.
508
+ *
509
+ * @function copyDirToNode
510
+ * @memberof UnderpostSSH
511
+ * @param {object} params
512
+ * @param {string} params.host - Target host/IP (key-only SSH reachable).
513
+ * @param {string} params.localDir - Local source directory.
514
+ * @param {string} params.remoteDir - Destination directory on the node.
515
+ * @param {number} [params.port=22] - SSH port.
516
+ * @param {string} [params.user='root'] - SSH user (key-only).
517
+ * @param {string} [params.keyPath='./engine-private/deploy/id_rsa'] - Private key path.
518
+ * @param {string} [params.owner='1000:1000'] - chown target on the node (empty to skip).
519
+ * @param {string} [params.mode='755'] - chmod mode on the node (empty to skip).
520
+ * @returns {void}
521
+ */
522
+ copyDirToNode: ({
523
+ host,
524
+ localDir,
525
+ remoteDir,
526
+ port = 22,
527
+ user = 'root',
528
+ keyPath = './engine-private/deploy/id_rsa',
529
+ owner = '1000:1000',
530
+ mode = '755',
531
+ }) => {
532
+ if (!host) throw new Error('copyDirToNode requires a host');
533
+ if (!localDir || !fs.existsSync(localDir)) throw new Error(`copyDirToNode: local dir not found: ${localDir}`);
534
+ if (!remoteDir) throw new Error('copyDirToNode requires a remoteDir');
535
+ try {
536
+ shellExec(`chmod 600 ${keyPath}`, { silent: true, silentOnError: true, disableLog: true });
537
+ const sshOpts = `-i ${keyPath} -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${port}`;
538
+ shellExec(`ssh ${sshOpts} ${user}@${host} 'mkdir -p ${remoteDir}'`, {
539
+ silent: true,
540
+ disableLog: true,
541
+ });
542
+ shellExec(`tar -C ${localDir} -c . | ssh ${sshOpts} ${user}@${host} 'tar -C ${remoteDir} -x'`, {
543
+ silent: true,
544
+ disableLog: true,
545
+ });
546
+ const fixups =
547
+ `${owner ? `chown -R ${owner} ${remoteDir}; ` : ''}${mode ? `chmod -R ${mode} ${remoteDir}` : ''}`.trim();
548
+ if (fixups)
549
+ shellExec(`ssh ${sshOpts} ${user}@${host} '${fixups}'`, {
550
+ silent: true,
551
+ disableLog: true,
552
+ });
553
+ } catch (err) {
554
+ logger.error(`copyDirToNode failed`);
555
+ process.exit(1);
556
+ }
557
+ },
558
+
559
+ /**
560
+ * Generic SSH remote command runner that SSH execution logic.
561
+ * Executes arbitrary shell commands on a remote server via SSH with proper credential handling.
562
+ * @async
563
+ * @function sshRemoteRunner
564
+ * @param {string} remoteCommand - The command to execute on the remote server
565
+ * @param {Object} options - Configuration options for SSH execution
566
+ * @param {string} [options.deployId] - Deployment ID for credential lookup
567
+ * @param {string} [options.user] - SSH user for credential lookup
568
+ * @param {boolean} [options.dev=false] - Development mode flag
569
+ * @param {string} [options.cd='/home/dd/engine'] - Working directory on remote server
570
+ * @param {boolean} [options.useSudo=true] - Whether to use sudo for command execution
571
+ * @param {boolean} [options.remote=true] - Whether to execute as remote command (if false, runs locally)
572
+ * @returns {Promise<string>} Output from the shell execution
573
+ * @memberof UnderpostSSH
574
+ */
575
+ sshRemoteRunner: async (remoteCommand, options = {}) => {
576
+ const { deployId = '', user = '', dev = false, cd = '/home/dd/engine', useSudo = true, remote = true } = options;
577
+
578
+ // If not executing remotely, just run locally
579
+ if (!remote) {
580
+ return shellExec(remoteCommand);
581
+ }
582
+
583
+ // Set up SSH credentials from config
584
+ if (deployId && user) {
585
+ await Underpost.ssh.setDefautlSshCredentials({ deployId, user });
586
+ }
587
+
588
+ // Build the complete SSH command
589
+ const sshScript = `#!/usr/bin/env bash
590
+ set -euo pipefail
591
+
592
+ REMOTE_USER=$(node bin config get --plain DEFAULT_SSH_USER)
593
+ REMOTE_HOST=$(node bin config get --plain DEFAULT_SSH_HOST)
594
+ REMOTE_PORT=$(node bin config get --plain DEFAULT_SSH_PORT)
595
+ SSH_KEY=$(node bin config get --plain DEFAULT_SSH_KEY_PATH)
596
+
597
+ chmod 600 "$SSH_KEY"
598
+
599
+ ssh -i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$REMOTE_USER@$REMOTE_HOST" -p $REMOTE_PORT sh <<EOF
600
+ ${cd ? `cd ${cd}` : ''}
601
+ ${useSudo ? `sudo -n -- /bin/bash -lc "${remoteCommand}"` : remoteCommand}
602
+ EOF
603
+ `;
604
+
605
+ return shellExec(sshScript, { stdout: true });
606
+ },
607
+
608
+ /**
609
+ * Waits until a TCP SSH port becomes reachable on a host.
610
+ * @async
611
+ * @function waitForSshPort
612
+ * @memberof UnderpostSSH
613
+ * @param {object} params
614
+ * @param {string} params.host - Target host/IP.
615
+ * @param {number} [params.port=22] - SSH port.
616
+ * @param {number} [params.timeoutMs=600000] - Maximum wait window.
617
+ * @param {number} [params.intervalMs=3000] - Poll interval.
618
+ * @returns {Promise<boolean>} True once the port accepts connections, false on timeout.
619
+ */
620
+ waitForSshPort: async ({ host, port = 22, timeoutMs = 10 * 60 * 1000, intervalMs = 3000 }) => {
621
+ const deadline = Date.now() + timeoutMs;
622
+ while (Date.now() < deadline) {
623
+ const probe = shellExec(
624
+ `timeout 5 bash -c '</dev/tcp/${host}/${port}' >/dev/null 2>&1 && echo open || echo closed`,
625
+ { silent: true, stdout: true, silentOnError: true, disableLog: true },
626
+ );
627
+ if (`${probe}`.trim() === 'open') return true;
628
+ await new Promise((r) => setTimeout(r, intervalMs));
629
+ }
630
+ logger.warn(`SSH port ${host}:${port} not reachable within timeout`);
631
+ return false;
632
+ },
633
+
634
+ /**
635
+ * Waits until a host's SSH port stops accepting connections (e.g. while it
636
+ * reboots). Used to detect a reboot edge before waiting for the port to come
637
+ * back up, so callers don't latch onto the pre-reboot (ephemeral) sshd.
638
+ * @async
639
+ * @function waitForSshPortClosed
640
+ * @memberof UnderpostSSH
641
+ * @param {object} params
642
+ * @param {string} params.host - Target host/IP.
643
+ * @param {number} [params.port=22] - SSH port.
644
+ * @param {number} [params.timeoutMs=180000] - Maximum wait window.
645
+ * @param {number} [params.intervalMs=3000] - Poll interval.
646
+ * @returns {Promise<boolean>} True once the port is closed, false on timeout.
647
+ */
648
+ waitForSshPortClosed: async ({ host, port = 22, timeoutMs = 3 * 60 * 1000, intervalMs = 3000 }) => {
649
+ const deadline = Date.now() + timeoutMs;
650
+ while (Date.now() < deadline) {
651
+ const probe = shellExec(
652
+ `timeout 5 bash -c '</dev/tcp/${host}/${port}' >/dev/null 2>&1 && echo open || echo closed`,
653
+ { silent: true, stdout: true, silentOnError: true, disableLog: true },
654
+ );
655
+ if (`${probe}`.trim() === 'closed') return true;
656
+ await new Promise((r) => setTimeout(r, intervalMs));
657
+ }
658
+ return false;
659
+ },
660
+
661
+ /**
662
+ * Orchestrates a non-interactive, key-only SSH session against a freshly
663
+ * provisioned host: waits for the port, attempts key-based auth, runs a
664
+ * remote command batch, and returns a structured result. Used by the
665
+ * commissioning flow once the ephemeral runtime reports SSH readiness.
666
+ * @async
667
+ * @function sshExecBatch
668
+ * @memberof UnderpostSSH
669
+ * @param {object} params
670
+ * @param {string} params.host - Target host/IP.
671
+ * @param {string} params.command - Remote command batch to execute.
672
+ * @param {number} [params.port=22] - SSH port.
673
+ * @param {string} [params.user='root'] - SSH user (key-only).
674
+ * @param {string} [params.keyPath] - Private key path (defaults to engine deploy key).
675
+ * @param {number} [params.connectTimeoutSec=15] - Per-attempt SSH connect timeout.
676
+ * @param {number} [params.retries=3] - Auth/exec retry attempts.
677
+ * @param {number} [params.retryDelayMs=5000] - Base backoff between retries.
678
+ * @param {number} [params.waitForPortMs=0] - When > 0, wait for the port first.
679
+ * @returns {Promise<{ok: boolean, code: number, stdout: string, stderr: string, attempts: number}>}
680
+ */
681
+ sshExecBatch: async ({
682
+ host,
683
+ command,
684
+ port = 22,
685
+ user = 'root',
686
+ keyPath = './engine-private/deploy/id_rsa',
687
+ connectTimeoutSec = 15,
688
+ retries = 3,
689
+ retryDelayMs = 5000,
690
+ waitForPortMs = 0,
691
+ }) => {
692
+ if (!host) throw new Error('sshExecBatch requires a host');
693
+ if (!command) throw new Error('sshExecBatch requires a command');
694
+
695
+ if (waitForPortMs > 0) {
696
+ const reachable = await Underpost.ssh.waitForSshPort({ host, port, timeoutMs: waitForPortMs });
697
+ if (!reachable) return { ok: false, code: 255, stdout: '', stderr: 'ssh port unreachable', attempts: 0 };
698
+ }
699
+
700
+ shellExec(`chmod 600 ${keyPath}`, { silent: true, silentOnError: true, disableLog: true });
701
+
702
+ const sshOpts = [
703
+ `-i ${keyPath}`,
704
+ `-o BatchMode=yes`,
705
+ `-o PreferredAuthentications=publickey`,
706
+ `-o PubkeyAuthentication=yes`,
707
+ `-o PasswordAuthentication=no`,
708
+ `-o StrictHostKeyChecking=no`,
709
+ `-o UserKnownHostsFile=/dev/null`,
710
+ `-o ConnectTimeout=${connectTimeoutSec}`,
711
+ // Tolerate a freshly-booted node whose network briefly flaps (e.g. while
712
+ // NetworkManager applies a static profile): retry the TCP connect and
713
+ // keep the session alive across short stalls.
714
+ `-o ConnectionAttempts=3`,
715
+ `-o ServerAliveInterval=10`,
716
+ `-o ServerAliveCountMax=6`,
717
+ `-p ${port}`,
718
+ ].join(' ');
719
+
720
+ let last = { ok: false, code: 255, stdout: '', stderr: '', attempts: 0 };
721
+ for (let attempt = 1; attempt <= retries; attempt++) {
722
+ const result = shellExec(
723
+ `ssh ${sshOpts} ${user}@${host} bash -s <<'UNDERPOST_SSH_BATCH_EOF'\n${command}\nUNDERPOST_SSH_BATCH_EOF`,
724
+ {
725
+ stdout: false,
726
+ silentOnError: true,
727
+ disableLog: true,
728
+ },
729
+ );
730
+ last = {
731
+ ok: result.code === 0,
732
+ code: result.code,
733
+ stdout: result.stdout || '',
734
+ stderr: result.stderr || '',
735
+ attempts: attempt,
736
+ };
737
+ if (last.ok) {
738
+ logger.info(`sshExecBatch succeeded on ${user}@${host}:${port} (attempt ${attempt})`);
739
+ return last;
740
+ }
741
+ logger.warn(`sshExecBatch attempt ${attempt}/${retries} failed on ${user}@${host}:${port}`, {
742
+ code: last.code,
743
+ stderr: last.stderr.slice(-400),
744
+ });
745
+ if (attempt < retries) await new Promise((r) => setTimeout(r, retryDelayMs * attempt));
746
+ }
747
+ return last;
748
+ },
749
+
750
+ /**
751
+ * Transfers a local script to a remote host and runs it over key-only SSH.
752
+ * The script is base64-encoded so no shell-quoting/escaping is needed, then
753
+ * decoded, made executable, and executed with the given arguments. Reuses
754
+ * sshExecBatch for the actual transport, retries, and structured result.
755
+ * @async
756
+ * @function sshRunScript
757
+ * @memberof UnderpostSSH
758
+ * @param {object} params
759
+ * @param {string} params.host - Target host/IP.
760
+ * @param {string} params.scriptPath - Local path to the script to run.
761
+ * @param {string} [params.args=''] - Arguments appended to the remote invocation.
762
+ * @param {object} [params.env={}] - Environment variables exported for the remote run (e.g. secrets). Passed inline to the command, never echoed.
763
+ * @param {string} [params.remotePath='/tmp/underpost-remote-script.sh'] - Remote path to write the script.
764
+ * @param {number} [params.port=22] - SSH port.
765
+ * @param {string} [params.user='root'] - SSH user (key-only).
766
+ * @param {string} [params.keyPath] - Private key path (defaults to engine deploy key).
767
+ * @param {number} [params.retries=3] - Retry attempts.
768
+ * @param {number} [params.waitForPortMs=0] - When > 0, wait for the port first.
769
+ * @returns {Promise<{ok: boolean, code: number, stdout: string, stderr: string, attempts: number}>}
770
+ */
771
+ sshRunScript: async ({
772
+ host,
773
+ scriptPath,
774
+ args = '',
775
+ env = {},
776
+ remotePath = '/tmp/underpost-remote-script.sh',
777
+ port = 22,
778
+ user = 'root',
779
+ keyPath = './engine-private/deploy/id_rsa',
780
+ retries = 3,
781
+ waitForPortMs = 0,
782
+ }) => {
783
+ if (!fs.existsSync(scriptPath)) throw new Error(`sshRunScript: script not found: ${scriptPath}`);
784
+ const b64 = Buffer.from(fs.readFileSync(scriptPath, 'utf8'), 'utf8').toString('base64');
785
+ // Inline env assignments (single-quote escaped) so secrets are exported for
786
+ // the remote run without appearing as logged CLI args.
787
+ const sq = (v) => `'${String(v).replace(/'/g, "'\\''")}'`;
788
+ const envPrefix = Object.entries(env)
789
+ .filter(([, v]) => v !== undefined && v !== null && `${v}` !== '')
790
+ .map(([k, v]) => `${k}=${sq(v)}`)
791
+ .join(' ');
792
+ const command = [
793
+ 'set -e',
794
+ `echo '${b64}' | base64 -d > ${remotePath}`,
795
+ `chmod +x ${remotePath}`,
796
+ `${envPrefix ? `${envPrefix} ` : ''}bash ${remotePath} ${args}`,
797
+ ].join('\n');
798
+ return Underpost.ssh.sshExecBatch({ host, port, user, keyPath, retries, waitForPortMs, command });
799
+ },
800
+
801
+ /**
802
+ * Loads saved SSH credentials from config and sets them in the UnderpostRootEnv API.
803
+ * @async
804
+ * @function setDefautlSshCredentials
805
+ * @memberof UnderpostSSH
806
+ * @param {Object} options - Options for setting default SSH credentials
807
+ * @param {string} options.deployId - Deployment ID for the config path
808
+ * @param {string} options.user - SSH user name
809
+ * @returns {Promise<void>}
810
+ */
811
+ setDefautlSshCredentials: async (options = { deployId: '', user: '' }) => {
812
+ const confNodePath = `./engine-private/conf/${options.deployId}/conf.node.json`;
813
+ if (fs.existsSync(confNodePath)) {
814
+ const { users } = JSON.parse(fs.readFileSync(confNodePath, 'utf8'));
815
+ const { user, host, keyPath, port } = users[options.user];
816
+ Underpost.env.set('DEFAULT_SSH_USER', user);
817
+ Underpost.env.set('DEFAULT_SSH_HOST', host);
818
+ Underpost.env.set('DEFAULT_SSH_KEY_PATH', keyPath);
819
+ Underpost.env.set('DEFAULT_SSH_PORT', port);
820
+ } else logger.warn(`No SSH config found at ${confNodePath}`);
821
+ },
822
+
823
+ /**
824
+ * Generates new SSH ED25519 key pair and stores copies in multiple locations.
825
+ * @function generateKeys
826
+ * @memberof UnderpostSSH
827
+ * @param {Object} params - Key generation parameters
828
+ * @param {string} params.user - Username for the SSH key comment
829
+ * @param {string} params.password - Password to encrypt the private key
830
+ * @param {string} params.host - Host address for the SSH key comment
831
+ * @returns {void}
832
+ * @description
833
+ * Creates a new SSH ED25519 key pair and distributes it to:
834
+ * - User's ~/.ssh/ directory
835
+ * - ./engine-private/deploy/ directory
836
+ * Cleans up temporary key files after copying.
837
+ */
838
+ generateKeys: ({ user, password, host }) => {
839
+ shellExec(`sudo rm -rf ./id_rsa`);
840
+ shellExec(`sudo rm -rf ./id_rsa.pub`);
841
+
842
+ shellExec(`ssh-keygen -t ed25519 -f id_rsa -N "${password}" -q -C "${user}@${host}"`);
843
+
844
+ shellExec(`sudo cp ./id_rsa ~/.ssh/id_rsa`);
845
+ shellExec(`sudo cp ./id_rsa.pub ~/.ssh/id_rsa.pub`);
846
+
847
+ shellExec(`sudo cp ./id_rsa ./engine-private/deploy/id_rsa`);
848
+ shellExec(`sudo cp ./id_rsa.pub ./engine-private/deploy/id_rsa.pub`);
849
+
850
+ shellExec(`sudo rm -rf ./id_rsa`);
851
+ shellExec(`sudo rm -rf ./id_rsa.pub`);
852
+ },
853
+
854
+ /**
855
+ * Sets proper permissions and ownership for SSH directories and files.
856
+ * @function chmod
857
+ * @memberof UnderpostSSH
858
+ * @param {Object} params - Permission configuration parameters
859
+ * @param {string} params.user - Username for setting ownership
860
+ * @returns {void}
861
+ * @description
862
+ * Applies secure permissions to SSH files:
863
+ * - ~/.ssh/ directory: 700
864
+ * - ~/.ssh/authorized_keys: 600
865
+ * - ~/.ssh/known_hosts: 644
866
+ * - ~/.ssh/id_rsa: 600
867
+ * - /etc/ssh/ssh_host_ed25519_key: 600
868
+ * Sets ownership to specified user for ~/.ssh/ and contents.
869
+ */
870
+ chmod: ({ user }) => {
871
+ shellExec(`sudo chmod 700 ~/.ssh/`);
872
+ shellExec(`sudo chmod 600 ~/.ssh/authorized_keys`);
873
+ shellExec(`sudo chmod 644 ~/.ssh/known_hosts`);
874
+ shellExec(`sudo chmod 600 ~/.ssh/id_rsa`);
875
+ shellExec(`sudo chmod 600 /etc/ssh/ssh_host_ed25519_key`);
876
+ shellExec(`chown -R ${user}:${user} ~/.ssh`);
877
+ },
878
+
879
+ /**
880
+ * Initializes and hardens SSH service configuration for RHEL-based systems.
881
+ * @function initService
882
+ * @memberof UnderpostSSH
883
+ * @param {Object} params - Service configuration parameters
884
+ * @param {number} params.port - Port number for SSH service
885
+ * @returns {void}
886
+ * @description
887
+ * Configures SSH daemon with hardened security settings:
888
+ * - Disables password authentication (key-only)
889
+ * - Disables root login
890
+ * - Enables ED25519 host key
891
+ * - Disables X11 forwarding and TCP forwarding
892
+ * - Sets client alive intervals to prevent ghost connections
893
+ * - Configures PAM for RHEL/SELinux compatibility
894
+ *
895
+ * After configuration:
896
+ * - Enables sshd service for auto-start on boot
897
+ * - Restarts sshd service to apply changes
898
+ * - Displays service status with colored output
899
+ */
900
+ initService: ({ port }) => {
901
+ shellExec(
902
+ `sudo tee /etc/ssh/sshd_config <<EOF
903
+ # ==============================================================
904
+ # RHEL Hardened SSHD Configuration
905
+ # ==============================================================
906
+
907
+ # --- Network Settings ---
908
+ Port ${port ? port : '22'}
909
+ # Explicitly listen on all interfaces (IPv4 and IPv6)
910
+
911
+ # --- Host Keys ---
912
+ # ED25519 is the modern standard (Fast & Secure)
913
+ HostKey /etc/ssh/ssh_host_ed25519_key
914
+ # RSA is kept for compatibility with older clients (Optional)
915
+ # HostKey /etc/ssh/ssh_host_rsa_key
916
+
917
+ # --- Logging ---
918
+ SyslogFacility AUTHPRIV
919
+ # VERBOSE logs the key fingerprint used for login (Audit trail)
920
+ LogLevel VERBOSE
921
+
922
+ # --- Authentication & Security ---
923
+ # STRICTLY KEY-BASED AUTHENTICATION
924
+ PubkeyAuthentication yes
925
+ PasswordAuthentication no
926
+ ChallengeResponseAuthentication no
927
+ PermitEmptyPasswords no
928
+
929
+ # PREVENT ROOT LOGIN
930
+ # Administrators should log in as a standard user and use 'sudo'
931
+ PermitRootLogin no
932
+
933
+ # Security checks on ownership of ~/.ssh/ files
934
+ StrictModes yes
935
+ MaxAuthTries 3
936
+ LoginGraceTime 60
937
+
938
+ # --- PAM (Pluggable Authentication Modules) ---
939
+ # REQUIRED: Must be 'yes' on RHEL for proper session/SELinux handling.
940
+ # Since PasswordAuthentication is 'no', PAM will not ask for passwords.
941
+ UsePAM yes
942
+
943
+ # --- Session & Network Health ---
944
+ # Disconnect idle sessions after 5 minutes (300s * 0) to prevent ghost connections
945
+ ClientAliveInterval 300
946
+ ClientAliveCountMax 0
947
+
948
+ # --- Feature Restrictions ---
949
+ # Disable GUI forwarding unless explicitly needed
950
+ X11Forwarding no
951
+ # Disable DNS checks for faster logins (unless you use Host based auth)
952
+ UseDNS no
953
+ # Disable tunneling unless needed
954
+ PermitTunnel no
955
+ AllowTcpForwarding no
956
+
957
+ # --- Subsystem ---
958
+ Subsystem sftp /usr/libexec/openssh/sftp-server
959
+ EOF`,
960
+ { disableLog: true },
961
+ );
962
+ shellExec(`sudo systemctl enable sshd`);
963
+ shellExec(`sudo systemctl restart sshd`);
964
+
965
+ const status = shellExec(`sudo systemctl status sshd`, { silent: true, stdout: true });
966
+ if (status.match('running')) console.log(status.replaceAll(`running`, `running`.green));
967
+ else {
968
+ logger.error('SSHD service failed to start');
969
+ console.log(status);
970
+ }
971
+ },
972
+ };
973
+ }
974
+
975
+ export default UnderpostSSH;