cyberia 3.2.5 → 3.2.12

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 (381) hide show
  1. package/.github/workflows/engine-cyberia.cd.yml +8 -2
  2. package/.github/workflows/npmpkg.ci.yml +1 -0
  3. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  4. package/.github/workflows/release.cd.yml +2 -2
  5. package/.vscode/extensions.json +9 -9
  6. package/.vscode/settings.json +20 -4
  7. package/CHANGELOG.md +563 -1
  8. package/CLI-HELP.md +130 -34
  9. package/Dockerfile +0 -4
  10. package/README.md +194 -607
  11. package/bin/build.js +42 -12
  12. package/bin/build.template.js +187 -0
  13. package/bin/cyberia.js +1367 -281
  14. package/bin/deploy.js +582 -3
  15. package/bin/index.js +1367 -281
  16. package/bump.config.js +26 -0
  17. package/conf.js +195 -111
  18. package/deployment.yaml +6 -222
  19. package/hardhat/package-lock.json +118 -149
  20. package/hardhat/package.json +5 -4
  21. package/jsconfig.json +1 -1
  22. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
  23. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +2 -2
  24. package/manifests/deployment/dd-cyberia-development/deployment.yaml +6 -222
  25. package/manifests/deployment/dd-cyberia-development/proxy.yaml +10 -118
  26. package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
  27. package/manifests/deployment/dd-test-development/deployment.yaml +138 -66
  28. package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
  29. package/manifests/kind-config-dev.yaml +8 -0
  30. package/manifests/lxd/lxd-admin-profile.yaml +12 -3
  31. package/manifests/mongodb/pv-pvc.yaml +44 -8
  32. package/manifests/mongodb/statefulset.yaml +55 -68
  33. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  34. package/manifests/mongodb-4.4/kustomization.yaml +3 -1
  35. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  36. package/manifests/mongodb-4.4/pv-pvc.yaml +10 -14
  37. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  38. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  39. package/manifests/valkey/statefulset.yaml +1 -1
  40. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  41. package/package.json +45 -24
  42. package/proxy.yaml +10 -118
  43. package/scripts/ipxe-setup.sh +52 -49
  44. package/scripts/k3s-node-setup.sh +83 -48
  45. package/scripts/lxd-vm-setup.sh +193 -8
  46. package/scripts/maas-nat-firewalld.sh +145 -0
  47. package/scripts/nat-iptables.sh +103 -18
  48. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +18 -18
  49. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +7 -14
  50. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +38 -33
  51. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +91 -36
  52. package/src/api/core/core.controller.js +10 -10
  53. package/src/api/core/core.router.js +19 -14
  54. package/src/api/core/core.service.js +15 -15
  55. package/src/api/crypto/crypto.controller.js +8 -8
  56. package/src/api/crypto/crypto.router.js +18 -12
  57. package/src/api/crypto/crypto.service.js +11 -11
  58. package/src/api/cyberia-action/cyberia-action.controller.js +74 -0
  59. package/src/api/cyberia-action/cyberia-action.model.js +87 -0
  60. package/src/api/cyberia-action/cyberia-action.router.js +31 -0
  61. package/src/api/cyberia-action/cyberia-action.service.js +42 -0
  62. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +74 -0
  63. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +99 -0
  64. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +98 -0
  65. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
  66. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +13 -13
  67. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +11 -11
  68. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +25 -20
  69. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +22 -22
  70. package/src/api/cyberia-entity/cyberia-entity.controller.js +10 -10
  71. package/src/api/cyberia-entity/cyberia-entity.router.js +22 -18
  72. package/src/api/cyberia-entity/cyberia-entity.service.js +15 -15
  73. package/src/api/cyberia-instance/cyberia-fallback-world.js +83 -198
  74. package/src/api/cyberia-instance/cyberia-instance.controller.js +14 -14
  75. package/src/api/cyberia-instance/cyberia-instance.model.js +3 -0
  76. package/src/api/cyberia-instance/cyberia-instance.router.js +57 -52
  77. package/src/api/cyberia-instance/cyberia-instance.service.js +32 -67
  78. package/src/api/cyberia-instance/cyberia-portal-connector.js +20 -246
  79. package/src/api/cyberia-instance/cyberia-world-generator.js +505 -0
  80. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +10 -10
  81. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +18 -49
  82. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +22 -18
  83. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +19 -15
  84. package/src/api/cyberia-map/cyberia-map.controller.js +10 -10
  85. package/src/api/cyberia-map/cyberia-map.router.js +35 -30
  86. package/src/api/cyberia-map/cyberia-map.service.js +17 -17
  87. package/src/api/cyberia-quest/cyberia-quest.controller.js +74 -0
  88. package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
  89. package/src/api/cyberia-quest/cyberia-quest.router.js +31 -0
  90. package/src/api/cyberia-quest/cyberia-quest.service.js +42 -0
  91. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +74 -0
  92. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
  93. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +31 -0
  94. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
  95. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +451 -0
  96. package/src/api/default/default.controller.js +10 -10
  97. package/src/api/default/default.router.js +22 -18
  98. package/src/api/default/default.service.js +15 -15
  99. package/src/api/document/document.controller.js +12 -12
  100. package/src/api/document/document.model.js +10 -16
  101. package/src/api/document/document.router.js +28 -23
  102. package/src/api/document/document.service.js +100 -23
  103. package/src/api/file/file.controller.js +8 -8
  104. package/src/api/file/file.model.js +10 -10
  105. package/src/api/file/file.router.js +19 -13
  106. package/src/api/file/file.service.js +45 -43
  107. package/src/api/instance/instance.controller.js +10 -10
  108. package/src/api/instance/instance.model.js +4 -10
  109. package/src/api/instance/instance.router.js +29 -24
  110. package/src/api/instance/instance.service.js +16 -16
  111. package/src/api/ipfs/ipfs.controller.js +12 -12
  112. package/src/api/ipfs/ipfs.model.js +4 -13
  113. package/src/api/ipfs/ipfs.router.js +21 -16
  114. package/src/api/ipfs/ipfs.service.js +22 -36
  115. package/src/api/object-layer/object-layer.controller.js +12 -12
  116. package/src/api/object-layer/object-layer.model.js +4 -17
  117. package/src/api/object-layer/object-layer.router.js +512 -507
  118. package/src/api/object-layer/object-layer.service.js +29 -26
  119. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +10 -10
  120. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +6 -16
  121. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +22 -18
  122. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +19 -15
  123. package/src/api/test/test.controller.js +8 -8
  124. package/src/api/test/test.router.js +17 -12
  125. package/src/api/test/test.service.js +8 -8
  126. package/src/api/types.js +24 -0
  127. package/src/api/user/guest.service.js +100 -0
  128. package/src/api/user/user.controller.js +6 -6
  129. package/src/api/user/user.model.js +8 -13
  130. package/src/api/user/user.router.js +297 -288
  131. package/src/api/user/user.service.js +103 -55
  132. package/src/cli/baremetal.js +132 -101
  133. package/src/cli/cluster.js +732 -217
  134. package/src/cli/db.js +106 -62
  135. package/src/cli/deploy.js +260 -149
  136. package/src/cli/fs.js +90 -9
  137. package/src/cli/image.js +43 -1
  138. package/src/cli/index.js +106 -16
  139. package/src/cli/ipfs.js +4 -6
  140. package/src/cli/kubectl.js +4 -1
  141. package/src/cli/lxd.js +1099 -223
  142. package/src/cli/monitor.js +9 -3
  143. package/src/cli/release.js +336 -86
  144. package/src/cli/repository.js +136 -53
  145. package/src/cli/run.js +599 -76
  146. package/src/cli/secrets.js +11 -2
  147. package/src/cli/ssh.js +1 -1
  148. package/src/cli/static.js +43 -115
  149. package/src/cli/test.js +9 -3
  150. package/src/client/Cryptokoyn.index.js +18 -21
  151. package/src/client/CyberiaPortal.index.js +19 -23
  152. package/src/client/Default.index.js +30 -36
  153. package/src/client/Itemledger.index.js +20 -26
  154. package/src/client/Underpost.index.js +19 -23
  155. package/src/client/components/core/404.js +4 -4
  156. package/src/client/components/core/500.js +4 -4
  157. package/src/client/components/core/Account.js +73 -60
  158. package/src/client/components/core/AgGrid.js +23 -33
  159. package/src/client/components/core/Alert.js +12 -13
  160. package/src/client/components/core/AppStore.js +1 -1
  161. package/src/client/components/core/Auth.js +40 -37
  162. package/src/client/components/core/Badge.js +7 -13
  163. package/src/client/components/core/BtnIcon.js +15 -17
  164. package/src/client/components/core/CalendarCore.js +42 -63
  165. package/src/client/components/core/Chat.js +13 -15
  166. package/src/client/components/core/ClientEvents.js +163 -0
  167. package/src/client/components/core/ColorPaletteElement.js +309 -0
  168. package/src/client/components/core/Content.js +17 -14
  169. package/src/client/components/core/Css.js +15 -71
  170. package/src/client/components/core/CssCore.js +12 -16
  171. package/src/client/components/core/D3Chart.js +4 -4
  172. package/src/client/components/core/Docs.js +64 -91
  173. package/src/client/components/core/DropDown.js +69 -91
  174. package/src/client/components/core/EventBus.js +96 -0
  175. package/src/client/components/core/EventsUI.js +14 -17
  176. package/src/client/components/core/FileExplorer.js +96 -228
  177. package/src/client/components/core/FullScreen.js +47 -75
  178. package/src/client/components/core/Input.js +24 -69
  179. package/src/client/components/core/Keyboard.js +25 -18
  180. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  181. package/src/client/components/core/LoadingAnimation.js +25 -31
  182. package/src/client/components/core/LogIn.js +41 -41
  183. package/src/client/components/core/LogOut.js +23 -14
  184. package/src/client/components/core/Modal.js +544 -219
  185. package/src/client/components/core/NotificationManager.js +14 -18
  186. package/src/client/components/core/Panel.js +54 -50
  187. package/src/client/components/core/PanelForm.js +81 -177
  188. package/src/client/components/core/Polyhedron.js +110 -214
  189. package/src/client/components/core/PublicProfile.js +39 -32
  190. package/src/client/components/core/Recover.js +48 -44
  191. package/src/client/components/core/Responsive.js +88 -32
  192. package/src/client/components/core/RichText.js +9 -18
  193. package/src/client/components/core/Router.js +24 -3
  194. package/src/client/components/core/SearchBox.js +37 -37
  195. package/src/client/components/core/SignUp.js +39 -30
  196. package/src/client/components/core/SocketIo.js +31 -2
  197. package/src/client/components/core/SocketIoHandler.js +6 -6
  198. package/src/client/components/core/ToggleSwitch.js +8 -20
  199. package/src/client/components/core/ToolTip.js +5 -17
  200. package/src/client/components/core/Translate.js +56 -59
  201. package/src/client/components/core/Validator.js +26 -16
  202. package/src/client/components/core/Wallet.js +15 -26
  203. package/src/client/components/core/Worker.js +211 -276
  204. package/src/client/components/core/windowGetDimensions.js +7 -7
  205. package/src/client/components/cryptokoyn/{MenuCryptokoyn.js → AppShellCryptokoyn.js} +57 -57
  206. package/src/client/components/cryptokoyn/CssCryptokoyn.js +15 -15
  207. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +6 -4
  208. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +6 -4
  209. package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
  210. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +4 -4
  211. package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +6 -4
  212. package/src/client/components/cyberia/InstanceEngineCyberia.js +141 -60
  213. package/src/client/components/cyberia/MapEngineCyberia.js +691 -214
  214. package/src/client/components/cyberia/ObjectLayerEngine.js +19 -0
  215. package/src/client/components/cyberia/ObjectLayerEngineModal.js +1204 -94
  216. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +196 -298
  217. package/src/client/components/cyberia/SharedDefaultsCyberia.js +330 -0
  218. package/src/client/components/cyberia-portal/{MenuCyberiaPortal.js → AppShellCyberiaPortal.js} +102 -102
  219. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +15 -15
  220. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +6 -4
  221. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +6 -4
  222. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +4 -4
  223. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +60 -0
  224. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +4 -4
  225. package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +6 -4
  226. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -4
  227. package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
  228. package/src/client/components/default/CssDefault.js +12 -12
  229. package/src/client/components/default/LogInDefault.js +6 -4
  230. package/src/client/components/default/LogOutDefault.js +6 -4
  231. package/src/client/components/default/RouterDefault.js +47 -0
  232. package/src/client/components/default/SettingsDefault.js +4 -4
  233. package/src/client/components/default/SignUpDefault.js +6 -4
  234. package/src/client/components/default/TranslateDefault.js +3 -3
  235. package/src/client/components/itemledger/{MenuItemledger.js → AppShellItemledger.js} +57 -57
  236. package/src/client/components/itemledger/CssItemledger.js +15 -15
  237. package/src/client/components/itemledger/LogInItemledger.js +6 -4
  238. package/src/client/components/itemledger/LogOutItemledger.js +6 -4
  239. package/src/client/components/itemledger/RouterItemledger.js +38 -0
  240. package/src/client/components/itemledger/SettingsItemledger.js +4 -4
  241. package/src/client/components/itemledger/SignUpItemledger.js +6 -4
  242. package/src/client/components/itemledger/TranslateItemledger.js +3 -3
  243. package/src/client/components/underpost/{MenuUnderpost.js → AppShellUnderpost.js} +88 -88
  244. package/src/client/components/underpost/CssUnderpost.js +14 -14
  245. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +4 -4
  246. package/src/client/components/underpost/DocumentSearchProvider.js +1 -1
  247. package/src/client/components/underpost/LabGalleryUnderpost.js +12 -15
  248. package/src/client/components/underpost/LogInUnderpost.js +6 -4
  249. package/src/client/components/underpost/LogOutUnderpost.js +6 -4
  250. package/src/client/components/underpost/RouterUnderpost.js +45 -0
  251. package/src/client/components/underpost/SettingsUnderpost.js +4 -4
  252. package/src/client/components/underpost/SignUpUnderpost.js +6 -4
  253. package/src/client/components/underpost/TranslateUnderpost.js +4 -4
  254. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +235 -0
  255. package/src/client/public/cyberia-docs/ARCHITECTURE.md +83 -0
  256. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +204 -0
  257. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +291 -0
  258. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +278 -0
  259. package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
  260. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +241 -0
  261. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
  262. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +279 -0
  263. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +206 -0
  264. package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
  265. package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
  266. package/src/client/public/cyberia-docs/WHITE-PAPER.md +732 -0
  267. package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +14 -20
  268. package/src/client/services/core/core.service.js +17 -49
  269. package/src/client/services/crypto/crypto.service.js +8 -13
  270. package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
  271. package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
  272. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +10 -16
  273. package/src/client/services/cyberia-entity/cyberia-entity.management.js +5 -5
  274. package/src/client/services/cyberia-entity/cyberia-entity.service.js +10 -16
  275. package/src/client/services/cyberia-instance/cyberia-instance.management.js +6 -6
  276. package/src/client/services/cyberia-instance/cyberia-instance.service.js +12 -18
  277. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +10 -16
  278. package/src/client/services/cyberia-map/cyberia-map.management.js +6 -6
  279. package/src/client/services/cyberia-map/cyberia-map.service.js +12 -18
  280. package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
  281. package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
  282. package/src/client/services/default/default.management.js +159 -267
  283. package/src/client/services/default/default.service.js +10 -16
  284. package/src/client/services/document/document.service.js +14 -19
  285. package/src/client/services/file/file.service.js +8 -13
  286. package/src/client/services/instance/instance.management.js +5 -5
  287. package/src/client/services/instance/instance.service.js +10 -15
  288. package/src/client/services/ipfs/ipfs.service.js +12 -18
  289. package/src/client/services/object-layer/object-layer.management.js +12 -12
  290. package/src/client/services/object-layer/object-layer.service.js +20 -26
  291. package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +10 -16
  292. package/src/client/services/test/test.service.js +8 -13
  293. package/src/client/services/user/guest.service.js +86 -0
  294. package/src/client/services/user/user.management.js +5 -5
  295. package/src/client/services/user/user.service.js +14 -20
  296. package/src/client/ssr/body/404.js +3 -3
  297. package/src/client/ssr/body/500.js +3 -3
  298. package/src/client/ssr/body/CacheControl.js +5 -2
  299. package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
  300. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +13 -6
  301. package/src/client/ssr/head/PwaItemledger.js +197 -60
  302. package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
  303. package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
  304. package/src/client/ssr/views/CyberiaServerMetrics.js +982 -0
  305. package/src/client/ssr/{offline → views}/Maintenance.js +12 -11
  306. package/src/client/ssr/{offline → views}/NoNetworkConnection.js +3 -3
  307. package/src/client/ssr/{pages → views}/Test.js +2 -2
  308. package/src/client/sw/core.sw.js +274 -0
  309. package/src/db/DataBaseProvider.js +115 -15
  310. package/src/db/mariadb/MariaDB.js +2 -1
  311. package/src/db/mongo/MongoBootstrap.js +657 -0
  312. package/src/db/mongo/MongooseDB.js +129 -21
  313. package/src/grpc/cyberia/grpc-server.js +185 -105
  314. package/src/index.js +1 -1
  315. package/src/runtime/cyberia-client/Dockerfile +101 -0
  316. package/src/runtime/cyberia-client/Dockerfile.dev +82 -0
  317. package/src/runtime/cyberia-server/Dockerfile +62 -0
  318. package/src/runtime/cyberia-server/Dockerfile.dev +71 -0
  319. package/src/runtime/express/Dockerfile +4 -4
  320. package/src/runtime/express/Express.js +2 -2
  321. package/src/runtime/lampp/Dockerfile +8 -7
  322. package/src/runtime/wp/Dockerfile +11 -17
  323. package/src/runtime/wp/Wp.js +8 -5
  324. package/src/server/atlas-sprite-sheet-generator.js +4 -2
  325. package/src/server/auth.js +2 -2
  326. package/src/server/client-build-docs.js +46 -47
  327. package/src/server/client-build.js +371 -132
  328. package/src/server/client-formatted.js +47 -16
  329. package/src/server/conf.js +91 -87
  330. package/src/server/data-query.js +32 -20
  331. package/src/server/dns.js +22 -0
  332. package/src/server/ipfs-client.js +232 -91
  333. package/src/server/object-layer.js +1 -6
  334. package/src/server/process.js +192 -45
  335. package/src/server/proxy.js +9 -2
  336. package/src/server/runtime.js +1 -1
  337. package/src/server/semantic-layer-generator-floor.js +11 -51
  338. package/src/server/semantic-layer-generator-resource.js +259 -0
  339. package/src/server/semantic-layer-generator-skin.js +41 -171
  340. package/src/server/semantic-layer-generator.js +122 -14
  341. package/src/server/shape-generator.js +108 -0
  342. package/src/server/start.js +34 -8
  343. package/src/server/valkey.js +143 -235
  344. package/src/ws/IoInterface.js +16 -16
  345. package/src/ws/core/channels/core.ws.chat.js +11 -11
  346. package/src/ws/core/channels/core.ws.mailer.js +29 -29
  347. package/src/ws/core/channels/core.ws.stream.js +19 -19
  348. package/src/ws/core/core.ws.connection.js +8 -8
  349. package/src/ws/core/core.ws.server.js +6 -5
  350. package/src/ws/default/channels/default.ws.main.js +10 -10
  351. package/src/ws/default/default.ws.connection.js +4 -4
  352. package/src/ws/default/default.ws.server.js +4 -3
  353. package/tsconfig.docs.json +15 -0
  354. package/typedoc.dd-cyberia.json +29 -0
  355. package/typedoc.json +29 -0
  356. package/WHITE-PAPER.md +0 -1540
  357. package/bin/file.js +0 -196
  358. package/bin/vs.js +0 -74
  359. package/bin/zed.js +0 -84
  360. package/hardhat/README.md +0 -531
  361. package/hardhat/WHITE-PAPER.md +0 -1540
  362. package/jsdoc.dd-cyberia.json +0 -68
  363. package/jsdoc.json +0 -68
  364. package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +0 -413
  365. package/src/api/object-layer/README.md +0 -672
  366. package/src/client/components/core/ColorPalette.js +0 -5267
  367. package/src/client/components/core/JoyStick.js +0 -80
  368. package/src/client/components/cryptokoyn/RoutesCryptokoyn.js +0 -39
  369. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +0 -223
  370. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +0 -62
  371. package/src/client/components/cyberia-portal/ServerCyberiaPortal.js +0 -136
  372. package/src/client/components/default/RoutesDefault.js +0 -49
  373. package/src/client/components/itemledger/RoutesItemledger.js +0 -40
  374. package/src/client/components/underpost/RoutesUnderpost.js +0 -47
  375. package/src/client/ssr/email/DefaultRecoverEmail.js +0 -21
  376. package/src/client/ssr/email/DefaultVerifyEmail.js +0 -17
  377. package/src/client/ssr/pages/CyberiaServerMetrics.js +0 -461
  378. package/src/client/sw/default.sw.js +0 -127
  379. package/src/client/sw/template.sw.js +0 -84
  380. package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +0 -305
  381. package/src/grpc/cyberia/README.md +0 -326
package/src/cli/deploy.js CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  buildPortProxyRouter,
10
10
  buildProxyRouter,
11
11
  Config,
12
+ cronDeployIdResolve,
12
13
  deployRangePortFactory,
13
14
  getDataDeploy,
14
15
  loadConfServerJson,
@@ -124,24 +125,59 @@ class UnderpostDeploy {
124
125
  * @param {string} namespace - Kubernetes namespace for the deployment.
125
126
  * @param {Array<object>} volumes - Volume configurations for the deployment.
126
127
  * @param {Array<string>} cmd - Command to run in the deployment container.
128
+ * @param {boolean} skipFullBuild - Whether to skip the full client bundle build during deployment.
129
+ * @param {boolean} pullBundle - Whether to pull the pre-built client bundle from Cloudinary before starting. Use together with skipFullBuild to skip the local build entirely.
130
+ * @param {string} [imagePullPolicy] - Container imagePullPolicy override (`Always`, `IfNotPresent`, `Never`). When omitted, defaults to `Never` for `localhost/` images and `IfNotPresent` otherwise.
127
131
  * @returns {string} - YAML deployment configuration for the specified deployment.
128
132
  * @memberof UnderpostDeploy
129
133
  */
130
- deploymentYamlPartsFactory({ deployId, env, suffix, resources, replicas, image, namespace, volumes, cmd }) {
134
+ deploymentYamlPartsFactory({
135
+ deployId,
136
+ env,
137
+ suffix,
138
+ resources,
139
+ replicas,
140
+ image,
141
+ namespace,
142
+ volumes,
143
+ cmd,
144
+ skipFullBuild,
145
+ pullBundle,
146
+ imagePullPolicy,
147
+ // K8S lifecycle + probe wiring. Pass-through structures shaped like the
148
+ // upstream Kubernetes API, spliced verbatim into the container spec.
149
+ // lifecycle: { postStart: { exec: { command: [...] } }, preStop: { exec: { command: [...] } } }
150
+ // readinessProbe: { tcpSocket: { port: 8081 }, ... }
151
+ // livenessProbe: { tcpSocket: { port: 8081 }, ... }
152
+ // containerPort: integer; rendered as ports[0].containerPort. Optional.
153
+ lifecycle,
154
+ readinessProbe,
155
+ livenessProbe,
156
+ containerPort,
157
+ }) {
131
158
  if (!cmd)
132
- cmd = [
133
- `npm install -g npm@11.2.0`,
134
- `npm install -g underpost`,
135
- `underpost secret underpost --create-from-env`,
136
- `underpost start --build --run ${deployId} ${env}`,
137
- ];
159
+ cmd =
160
+ pullBundle || skipFullBuild
161
+ ? [
162
+ // When pullBundle (or skipFullBuild) is set the container pulls the pre-built client
163
+ // bundle from Cloudinary (push-bundle must have been run on the dev machine beforehand).
164
+ `underpost secret underpost --create-from-env`,
165
+ `underpost start --build --run --pull-bundle --skip-full-build ${deployId} ${env}`,
166
+ ]
167
+ : [
168
+ // `npm install -g npm@11.2.0`,
169
+ // `npm install -g underpost`,
170
+ `underpost secret underpost --create-from-env`,
171
+ `underpost start --build --run ${deployId} ${env}`,
172
+ ];
138
173
  const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
139
174
  if (!volumes) volumes = [];
140
175
  const confVolume = fs.existsSync(`./engine-private/conf/${deployId}/conf.volume.json`)
141
176
  ? JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.volume.json`, 'utf8'))
142
177
  : [];
143
178
  volumes = volumes.concat(confVolume);
144
- const containerImage = image ? image : `localhost/rockylinux9-underpost:v${packageJson.version}`;
179
+ // const containerImage = image ? image : `localhost/rockylinux9-underpost:v${packageJson.version}`;
180
+ const containerImage = image ? image : `underpost/underpost-engine:v${packageJson.version}`;
145
181
  return `apiVersion: apps/v1
146
182
  kind: Deployment
147
183
  metadata:
@@ -164,25 +200,60 @@ spec:
164
200
  containers:
165
201
  - name: ${deployId}-${env}-${suffix}
166
202
  image: ${containerImage}
203
+ imagePullPolicy: ${imagePullPolicy ? imagePullPolicy : containerImage.startsWith('localhost/') ? 'Never' : 'IfNotPresent'}
167
204
  envFrom:
168
205
  - secretRef:
169
206
  name: underpost-config
170
207
  ${
171
- resources
172
- ? ` resources:
208
+ containerPort
209
+ ? ` ports:
210
+ - containerPort: ${containerPort}
211
+ `
212
+ : ''
213
+ }${
214
+ resources
215
+ ? ` resources:
173
216
  requests:
174
217
  memory: "${resources.requests.memory}"
175
218
  cpu: "${resources.requests.cpu}"
176
219
  limits:
177
220
  memory: "${resources.limits.memory}"
178
221
  cpu: "${resources.limits.cpu}"`
179
- : ''
180
- }
222
+ : ''
223
+ }
181
224
  command:
182
225
  - /bin/sh
183
226
  - -c
184
227
  - >
185
228
  ${cmd.join(' &&\n ')}
229
+ ${
230
+ readinessProbe
231
+ ? ` readinessProbe:
232
+ ${JSON.stringify(readinessProbe, null, 2)
233
+ .split('\n')
234
+ .map((l) => ' ' + l)
235
+ .join('\n')}
236
+ `
237
+ : ''
238
+ }${
239
+ livenessProbe
240
+ ? ` livenessProbe:
241
+ ${JSON.stringify(livenessProbe, null, 2)
242
+ .split('\n')
243
+ .map((l) => ' ' + l)
244
+ .join('\n')}
245
+ `
246
+ : ''
247
+ }${
248
+ lifecycle
249
+ ? ` lifecycle:
250
+ ${JSON.stringify(lifecycle, null, 2)
251
+ .split('\n')
252
+ .map((l) => ' ' + l)
253
+ .join('\n')}
254
+ `
255
+ : ''
256
+ }
186
257
 
187
258
  ${
188
259
  volumes.length > 0
@@ -221,6 +292,9 @@ spec:
221
292
  * @param {string} [options.retryPerTryTimeout] - Retry per-try timeout setting for the deployment.
222
293
  * @param {boolean} [options.disableDeploymentProxy] - Whether to disable deployment proxy.
223
294
  * @param {string} [options.traffic] - Traffic status for the deployment.
295
+ * @param {boolean} [options.skipFullBuild] - Whether to skip the full client bundle build; forwarded to deploymentYamlPartsFactory to generate a pull-bundle startup command.
296
+ * @param {boolean} [options.pullBundle] - Whether to pull the pre-built client bundle from Cloudinary; forwarded to deploymentYamlPartsFactory. Use together with skipFullBuild.
297
+ * @param {string} [options.imagePullPolicy] - Container imagePullPolicy override (`Always`, `IfNotPresent`, `Never`); forwarded to deploymentYamlPartsFactory. When omitted, the builder defaults to `Never` for `localhost/` images and `IfNotPresent` otherwise.
224
298
  * @returns {Promise<void>} - Promise that resolves when the manifest is built.
225
299
  * @memberof UnderpostDeploy
226
300
  */
@@ -257,6 +331,9 @@ ${Underpost.deploy
257
331
  image,
258
332
  namespace: options.namespace,
259
333
  cmd: options.cmd ? options.cmd.split(',').map((c) => c.trim()) : undefined,
334
+ skipFullBuild: options.skipFullBuild,
335
+ pullBundle: options.pullBundle,
336
+ imagePullPolicy: options.imagePullPolicy,
260
337
  })
261
338
  .replace('{{ports}}', buildKindPorts(fromPort, toPort))}
262
339
  `;
@@ -480,10 +557,15 @@ spec:
480
557
  const hostTest = options?.hostTest
481
558
  ? options.hostTest
482
559
  : Object.keys(loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`))[0];
560
+ // Missing HTTPProxy is the canonical "no traffic colour set yet" state
561
+ // for blue/green rollouts. silentOnError swallows kubectl's NotFound
562
+ // exit so the function can return null cleanly.
483
563
  const info = shellExec(`sudo kubectl get HTTPProxy/${hostTest} -n ${options.namespace} -o yaml`, {
484
564
  silent: true,
485
565
  stdout: true,
566
+ silentOnError: true,
486
567
  });
568
+ if (!info) return null;
487
569
  return info.match('blue') ? 'blue' : info.match('green') ? 'green' : null;
488
570
  },
489
571
 
@@ -534,13 +616,11 @@ spec:
534
616
  * @param {string} options.traffic - Traffic status for the deployment.
535
617
  * @param {string} options.replicas - Number of replicas for the deployment.
536
618
  * @param {string} options.node - Node name for resource allocation.
537
- * @param {boolean} options.restoreHosts - Whether to restore the hosts file.
538
619
  * @param {boolean} options.disableUpdateDeployment - Whether to disable deployment updates.
539
620
  * @param {boolean} options.disableUpdateProxy - Whether to disable proxy updates.
540
621
  * @param {boolean} options.disableDeploymentProxy - Whether to disable deployment proxy.
541
622
  * @param {boolean} options.disableUpdateVolume - Whether to disable volume updates.
542
623
  * @param {boolean} options.status - Whether to display deployment status.
543
- * @param {boolean} options.etcHosts - Whether to display the /etc/hosts file.
544
624
  * @param {boolean} options.disableUpdateUnderpostConfig - Whether to disable Underpost config updates.
545
625
  * @param {string} [options.namespace] - Kubernetes namespace for the deployment.
546
626
  * @param {string} [options.timeoutResponse] - Timeout response setting for the deployment.
@@ -550,10 +630,14 @@ spec:
550
630
  * @param {string} [options.kindType] - Type of Kubernetes resource to retrieve information for.
551
631
  * @param {number} [options.port] - Port number for exposing the deployment.
552
632
  * @param {string} [options.cmd] - Custom initialization command for deploymentYamlPartsFactory (comma-separated commands).
633
+ * @param {number} [options.exposePort] - Local:remote port override when --expose is active (overrides auto-detected service port).
553
634
  * @param {boolean} [options.k3s] - Whether to use k3s cluster context.
554
635
  * @param {boolean} [options.kubeadm] - Whether to use kubeadm cluster context.
555
636
  * @param {boolean} [options.kind] - Whether to use kind cluster context.
556
637
  * @param {boolean} [options.gitClean] - Whether to run git clean on volume mount paths before copying.
638
+ * @param {boolean} [options.skipFullBuild] - Whether to skip the full client bundle build; passed through to buildManifest/deploymentYamlPartsFactory.
639
+ * @param {boolean} [options.pullBundle] - Whether to pull the pre-built client bundle from Cloudinary; passed through to buildManifest/deploymentYamlPartsFactory. Use together with skipFullBuild.
640
+ * @param {string} [options.imagePullPolicy] - Container imagePullPolicy override (`Always`, `IfNotPresent`, `Never`); passed through to buildManifest/deploymentYamlPartsFactory. When omitted, the builder defaults to `Never` for `localhost/` images and `IfNotPresent` otherwise.
557
641
  * @returns {Promise<void>} - Promise that resolves when the deployment process is complete.
558
642
  * @memberof UnderpostDeploy
559
643
  */
@@ -574,13 +658,11 @@ spec:
574
658
  traffic: '',
575
659
  replicas: '',
576
660
  node: '',
577
- restoreHosts: false,
578
661
  disableUpdateDeployment: false,
579
662
  disableUpdateProxy: false,
580
663
  disableDeploymentProxy: false,
581
664
  disableUpdateVolume: false,
582
665
  status: false,
583
- etcHosts: false,
584
666
  disableUpdateUnderpostConfig: false,
585
667
  namespace: '',
586
668
  timeoutResponse: '',
@@ -595,6 +677,7 @@ spec:
595
677
  kubeadm: false,
596
678
  kind: false,
597
679
  gitClean: false,
680
+ imagePullPolicy: '',
598
681
  },
599
682
  ) {
600
683
  const namespace = options.namespace ? options.namespace : 'default';
@@ -624,6 +707,8 @@ EOF`);
624
707
  path: instance.path,
625
708
  fromPort: instance.fromPort,
626
709
  toPort: instance.toPort,
710
+ fromDebugPort: instance.fromDebugPort,
711
+ toDebugPort: instance.toDebugPort,
627
712
  traffic: Underpost.deploy.getCurrentTraffic(_deployId, { namespace, hostTest: instance.host }),
628
713
  });
629
714
  }
@@ -661,14 +746,6 @@ EOF`);
661
746
  return;
662
747
  }
663
748
  if (!options.disableUpdateUnderpostConfig) Underpost.deploy.configMap(env);
664
- let renderHosts = '';
665
- let etcHosts = [];
666
- if (options.restoreHosts === true) {
667
- const factoryResult = Underpost.deploy.etcHostFactory(etcHosts);
668
- renderHosts = factoryResult.renderHosts;
669
- logger.info(renderHosts);
670
- return;
671
- }
672
749
 
673
750
  for (const _deployId of deployList.split(',')) {
674
751
  const deployId = _deployId.trim();
@@ -676,6 +753,10 @@ EOF`);
676
753
  if (options.expose === true) {
677
754
  const kindType = options.kindType ? options.kindType : 'svc';
678
755
  const svc = Underpost.kubectl.get(deployId, kindType)[0];
756
+ if (!svc) {
757
+ logger.error(`No ${kindType} found matching '${deployId}', skipping expose`);
758
+ continue;
759
+ }
679
760
  const port = options.exposePort
680
761
  ? parseInt(options.exposePort)
681
762
  : options.port
@@ -725,7 +806,6 @@ EOF`);
725
806
  if (Underpost.deploy.isValidTLSContext({ host, env, options }))
726
807
  shellExec(`sudo kubectl delete Certificate ${host} -n ${namespace} --ignore-not-found`);
727
808
  }
728
- if (!options.remove) etcHosts.push(host);
729
809
  }
730
810
 
731
811
  const manifestsPath =
@@ -746,15 +826,6 @@ EOF`);
746
826
  shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml -n ${namespace}`);
747
827
  }
748
828
  }
749
- if (options.etcHosts === true) {
750
- const factoryResult = Underpost.deploy.etcHostFactory(etcHosts);
751
- renderHosts = factoryResult.renderHosts;
752
- }
753
- if (renderHosts)
754
- logger.info(
755
- `
756
- ` + renderHosts,
757
- );
758
829
  },
759
830
  /**
760
831
  * Checks the status of a deployment.
@@ -767,25 +838,41 @@ EOF`);
767
838
  * @memberof UnderpostDeploy
768
839
  */
769
840
  async checkDeploymentReadyStatus(deployId, env, traffic, ignoresNames = [], namespace = 'default') {
770
- const cmd = `underpost config get container-status`;
771
841
  const pods = Underpost.kubectl.get(`${deployId}-${env}-${traffic}`, 'pods', namespace);
772
842
  const readyPods = [];
773
843
  const notReadyPods = [];
844
+
845
+ // Readiness signal: the pod's Kubernetes `Ready` condition driven by the
846
+ // container's readinessProbe (TCP socket, HTTP get, or exec). Set by kubelet
847
+ // when the probe passes. A failed or crashing runtime never becomes Ready —
848
+ // kubelet surfaces CrashLoopBackOff and this gate stays closed.
774
849
  for (const pod of pods) {
775
850
  const { NAME } = pod;
776
851
  if (ignoresNames && ignoresNames.find((t) => NAME.trim().toLowerCase().match(t.trim().toLowerCase()))) continue;
777
- const out = await new Promise((resolve) => {
778
- shellExec(`sudo kubectl exec -i ${NAME} -n ${namespace} -- sh -c "${cmd}"`, {
852
+
853
+ let podJson = null;
854
+ try {
855
+ // Pod may not exist yet (between deployment apply and pod
856
+ // scheduling). silentOnError lets the monitor loop continue
857
+ // instead of aborting on the transient NotFound exit.
858
+ const raw = shellExec(`sudo kubectl get pod ${NAME} -n ${namespace} -o json`, {
779
859
  silent: true,
780
860
  disableLog: true,
781
- callback: function (code, stdout, stderr) {
782
- return resolve(JSON.stringify({ code, stdout, stderr }));
783
- },
861
+ stdout: true,
862
+ silentOnError: true,
784
863
  });
785
- });
786
- pod.out = out;
787
- const ready = out.match(`${deployId}-${env}-running-deployment`);
788
- ready ? readyPods.push(pod) : notReadyPods.push(pod);
864
+ podJson = raw ? JSON.parse(raw) : null;
865
+ } catch (_) {
866
+ podJson = null;
867
+ }
868
+ const conditions = podJson?.status?.conditions || [];
869
+ const readyCondition = conditions.find((c) => c.type === 'Ready');
870
+ const k8sReady = readyCondition?.status === 'True';
871
+
872
+ pod.out = JSON.stringify({ k8sReady, condition: readyCondition ?? null });
873
+
874
+ if (k8sReady) readyPods.push(pod);
875
+ else notReadyPods.push(pod);
789
876
  }
790
877
  return {
791
878
  ready: pods.length > 0 && notReadyPods.length === 0,
@@ -801,9 +888,10 @@ EOF`);
801
888
  * @memberof UnderpostDeploy
802
889
  */
803
890
  configMap(env, namespace = 'default') {
891
+ const cronDeployId = cronDeployIdResolve() || 'dd-cron';
804
892
  shellExec(`kubectl delete secret underpost-config -n ${namespace} --ignore-not-found`);
805
893
  shellExec(
806
- `kubectl create secret generic underpost-config --from-env-file=/home/dd/engine/engine-private/conf/dd-cron/.env.${env} --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
894
+ `kubectl create secret generic underpost-config --from-env-file=/home/dd/engine/engine-private/conf/${cronDeployId}/.env.${env} --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
807
895
  );
808
896
  },
809
897
  /**
@@ -818,6 +906,7 @@ EOF`);
818
906
  * @param {string} options.timeoutIdle - Timeout idle setting for the deployment.
819
907
  * @param {string} options.retryCount - Retry count setting for the deployment.
820
908
  * @param {string} options.retryPerTryTimeout - Retry per-try timeout setting for the deployment.
909
+ * @param {string} [options.imagePullPolicy] - Container imagePullPolicy override; forwarded to the manifest rebuild triggered here.
821
910
  * @memberof UnderpostDeploy
822
911
  */
823
912
  switchTraffic(
@@ -831,12 +920,14 @@ EOF`);
831
920
  timeoutIdle: '',
832
921
  retryCount: '',
833
922
  retryPerTryTimeout: '',
923
+ imagePullPolicy: '',
834
924
  },
835
925
  ) {
836
926
  const timeoutFlags = Underpost.deploy.timeoutFlagsFactory(options);
927
+ const imagePullPolicyFlag = options.imagePullPolicy ? ` --image-pull-policy ${options.imagePullPolicy}` : '';
837
928
 
838
929
  shellExec(
839
- `node bin deploy --info-router --build-manifest --traffic ${targetTraffic} --replicas ${replicas} --namespace ${namespace}${timeoutFlags} ${deployId} ${env}`,
930
+ `node bin deploy --info-router --build-manifest --traffic ${targetTraffic} --replicas ${replicas} --namespace ${namespace}${timeoutFlags}${imagePullPolicyFlag} ${deployId} ${env}`,
840
931
  );
841
932
 
842
933
  shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml -n ${namespace}`);
@@ -1035,42 +1126,6 @@ spec:
1035
1126
  storage: 5Gi`;
1036
1127
  },
1037
1128
 
1038
- /**
1039
- * Creates a hosts file for a deployment.
1040
- * @param {Array<string>} hosts - List of hosts to be added to the hosts file.
1041
- * @param {object} options - Options for the hosts file creation.
1042
- * @param {boolean} options.append - Whether to append to the existing hosts file.
1043
- * @returns {object} - Object containing the rendered hosts file.
1044
- * @memberof UnderpostDeploy
1045
- */
1046
- etcHostFactory(hosts = [], options = { append: false }) {
1047
- hosts = hosts.map((host) => {
1048
- try {
1049
- if (!host.startsWith('http')) host = `http://${host}`;
1050
- const hostname = new URL(host).hostname;
1051
- logger.info('Hostname extract valid', { host, hostname });
1052
- return hostname;
1053
- } catch (e) {
1054
- logger.warn('No hostname extract valid', host);
1055
- return host;
1056
- }
1057
- });
1058
- const renderHosts = `127.0.0.1 ${hosts.join(
1059
- ' ',
1060
- )} localhost localhost.localdomain localhost4 localhost4.localdomain4
1061
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
1062
-
1063
- if (options && options.append && fs.existsSync(`/etc/hosts`)) {
1064
- fs.writeFileSync(
1065
- `/etc/hosts`,
1066
- fs.readFileSync(`/etc/hosts`, 'utf8') +
1067
- `
1068
- ${renderHosts}`,
1069
- 'utf8',
1070
- );
1071
- } else fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
1072
- return { renderHosts };
1073
- },
1074
1129
  /**
1075
1130
  * Checks if a TLS context is valid.
1076
1131
  * @param {object} options - Options for the check.
@@ -1084,94 +1139,122 @@ ${renderHosts}`,
1084
1139
  env === 'production' &&
1085
1140
  options.cert === true &&
1086
1141
  (!options.certHosts || options.certHosts.split(',').includes(host)),
1087
-
1088
1142
  /**
1089
1143
  * Monitors the ready status of a deployment.
1144
+ *
1145
+ * Ready signal:
1146
+ * The orchestrator gate is the Kubernetes pod Ready condition. When the
1147
+ * container's `readinessProbe` succeeds, kubelet flips
1148
+ * `status.conditions[Ready]` to True and `checkDeploymentReadyStatus`
1149
+ * returns the pod in `readyPods`. This is the only required signal — see
1150
+ * `src/client/public/nexodev/docs/references/Deploy custom instance to K8S.md`.
1151
+ *
1152
+ * Container-status:
1153
+ * `underpost config get container-status` is read from each pod for both
1154
+ * the display column and as a second ready gate alongside the K8S Ready
1155
+ * condition. Both must be satisfied before the monitor exits:
1156
+ * 1. K8S readinessProbe (TCP socket) — ensures the port is bound.
1157
+ * 2. container-status == `<deploy>-<env>-running-deployment` — ensures
1158
+ * the application has completed its own startup sequence.
1159
+ * Early-abort on `error` container-status remains in effect.
1160
+ *
1090
1161
  * @param {string} deployId - Deployment ID for which the ready status is being monitored.
1091
1162
  * @param {string} env - Environment for which the ready status is being monitored.
1092
1163
  * @param {string} targetTraffic - Target traffic status for the deployment.
1093
1164
  * @param {Array<string>} ignorePods - List of pod names to ignore.
1094
1165
  * @param {string} [namespace='default'] - Kubernetes namespace for the deployment.
1095
- * @param {string} [outLogType=''] - Type of log output.
1096
1166
  * @returns {object} - Object containing the ready status of the deployment.
1097
1167
  * @memberof UnderpostDeploy
1098
1168
  */
1099
- async monitorReadyRunner(deployId, env, targetTraffic, ignorePods = [], namespace = 'default', outLogType = '') {
1100
- let checkStatusIteration = 0;
1101
- const checkStatusIterationMsDelay = 1000;
1169
+ async monitorReadyRunner(deployId, env, targetTraffic, ignorePods = [], namespace = 'default') {
1170
+ const delayMs = 1000;
1102
1171
  const maxIterations = 3000;
1103
1172
  const deploymentId = `${deployId}-${env}-${targetTraffic}`;
1104
- const iteratorTag = `[${deploymentId}]`;
1105
- logger.info('Deployment init', { deployId, env, targetTraffic, checkStatusIterationMsDelay, namespace });
1106
- const minReadyOk = 3;
1107
- let readyOk = 0;
1108
- let result = {
1109
- ready: false,
1110
- notReadyPods: [],
1111
- readyPods: [],
1112
- };
1113
- let lastMsg = {};
1114
- while (readyOk < minReadyOk) {
1115
- if (checkStatusIteration >= maxIterations) {
1116
- logger.error(
1117
- `${iteratorTag} | Deployment check ready status timeout. Max iterations reached: ${maxIterations}`,
1173
+ const expectedContainerStatus = `${deployId}-${env}-running-deployment`;
1174
+ const tag = `[${deploymentId}]`;
1175
+ const containerStatusDefault = 'waiting for status';
1176
+
1177
+ logger.info('Deployment init', { deployId, env, targetTraffic, namespace });
1178
+
1179
+ // Per-pod cache of last-known container-status (persists across retries)
1180
+ const podStatusCache = new Map();
1181
+
1182
+ const readContainerStatus = (podName) => {
1183
+ try {
1184
+ const raw = shellExec(
1185
+ `sudo kubectl exec ${podName} -n ${namespace} -- sh -c 'underpost config get container-status --plain'`,
1186
+ { silent: true, disableLog: true, stdout: true, silentOnError: true },
1118
1187
  );
1119
- break;
1188
+ const val = raw ? raw.toString().trim() : '';
1189
+ return val && val !== 'undefined' ? val : containerStatusDefault;
1190
+ } catch (_) {
1191
+ // exec failed (e.g. pod not yet running) — preserve last known value
1192
+ return podStatusCache.get(podName) || containerStatusDefault;
1120
1193
  }
1121
- result = await Underpost.deploy.checkDeploymentReadyStatus(deployId, env, targetTraffic, ignorePods, namespace);
1122
- if (result.ready === true) {
1123
- readyOk++;
1124
- logger.info(`${iteratorTag} | Deployment ready. Verification number: ${readyOk}`);
1125
- for (const pod of result.readyPods) {
1126
- const { NAME } = pod;
1127
- lastMsg[NAME] = 'Deployment ready';
1128
- console.log(
1129
- 'Target pod:',
1130
- NAME[NAME.match('green') ? 'bgGreen' : 'bgBlue'].bold.black,
1131
- '| Status:',
1132
- lastMsg[NAME].bold.magenta,
1133
- );
1134
- }
1194
+ };
1195
+
1196
+ for (let i = 0; i < maxIterations; i++) {
1197
+ const result = await Underpost.deploy.checkDeploymentReadyStatus(
1198
+ deployId,
1199
+ env,
1200
+ targetTraffic,
1201
+ ignorePods,
1202
+ namespace,
1203
+ );
1204
+
1205
+ const allPods = [...result.readyPods, ...result.notReadyPods];
1206
+
1207
+ // Update cache with latest status for each pod (informational + error gate)
1208
+ for (const pod of allPods) {
1209
+ if (!pod?.NAME) continue;
1210
+ const status = readContainerStatus(pod.NAME);
1211
+ if (status === 'error') throw new Error(`Pod ${pod.NAME} has error status`);
1212
+ podStatusCache.set(pod.NAME, status);
1135
1213
  }
1136
1214
 
1137
- switch (outLogType) {
1138
- case 'underpost': {
1139
- let indexOf = -1;
1140
- for (const pod of result.notReadyPods) {
1141
- indexOf++;
1142
- const { NAME, out } = pod;
1215
+ const allPodsK8sReady = allPods.length > 0 && result.notReadyPods.length === 0;
1143
1216
 
1144
- if (out.match('not') && out.match('found') && checkStatusIteration <= 20 && out.match(deploymentId))
1145
- lastMsg[NAME] = 'Starting deployment';
1146
- else if (out.match('not') && out.match('found') && checkStatusIteration <= 20 && out.match('underpost'))
1147
- lastMsg[NAME] = 'Installing underpost cli';
1148
- else if (out.match('not') && out.match('found') && checkStatusIteration <= 20 && out.match('task'))
1149
- lastMsg[NAME] = 'Initializing setup task';
1150
- else if (out.match('Empty environment variables')) lastMsg[NAME] = 'Setup environment';
1151
- else if (out.match(`${deployId}-${env}-build-deployment`)) lastMsg[NAME] = 'Building apps/services';
1152
- else if (out.match(`${deployId}-${env}-initializing-deployment`))
1153
- lastMsg[NAME] = 'Initializing apps/services';
1154
- else if (!lastMsg[NAME]) lastMsg[NAME] = `Waiting for status`;
1217
+ const allPodsStatusReady =
1218
+ allPods.length > 0 && allPods.every((pod) => podStatusCache.get(pod.NAME) === expectedContainerStatus);
1155
1219
 
1156
- console.log(
1157
- 'Target pod:',
1158
- NAME[NAME.match('green') ? 'bgGreen' : 'bgBlue'].bold.black,
1159
- '| Status:',
1160
- lastMsg[NAME].bold.magenta,
1161
- );
1162
- }
1163
- }
1220
+ // Print snapshot for every pod — annotate when container-status hasn't caught
1221
+ // up to the K8S Ready condition yet.
1222
+ for (const pod of allPods) {
1223
+ const status = podStatusCache.get(pod.NAME) || containerStatusDefault;
1224
+ const podStatus = pod.STATUS || 'Unknown';
1225
+ const statusMatchesExpected = status === expectedContainerStatus;
1226
+ const statusDisplay = statusMatchesExpected ? status : `${status} (pending)`;
1227
+
1228
+ console.log(
1229
+ 'Target pod:',
1230
+ pod.NAME[pod.NAME.includes('green') ? 'bgGreen' : 'bgBlue'].bold.black,
1231
+ '| Pod status:',
1232
+ podStatus.bold.yellow,
1233
+ '| Runtime status:',
1234
+ statusDisplay.bold.cyan,
1235
+ );
1236
+ }
1237
+
1238
+ // Both K8S readinessProbe AND container-status must be satisfied before
1239
+ // declaring the deployment ready. The TCP probe ensures the port is bound;
1240
+ // container-status == running-deployment ensures the application has
1241
+ // completed its own startup sequence so traffic is not switched prematurely.
1242
+ if (allPodsK8sReady && allPodsStatusReady) {
1243
+ logger.info(`${tag} | All pods Ready (K8S readinessProbe satisfied)`);
1244
+ return result;
1245
+ }
1246
+
1247
+ await timer(delayMs);
1248
+
1249
+ if ((i + 1) % 10 === 0) {
1250
+ logger.info(`${tag} | In progress... iteration ${i + 1}`);
1164
1251
  }
1165
- await timer(checkStatusIterationMsDelay);
1166
- checkStatusIteration++;
1167
- logger.info(
1168
- `${iteratorTag} | Deployment in progress... | Delay number monitor iterations: ${checkStatusIteration}`,
1169
- );
1170
1252
  }
1171
- logger.info(
1172
- `${iteratorTag} | Deployment ready. | Total delay number monitor iterations: ${checkStatusIteration}`,
1253
+
1254
+ logger.error(`${tag} | Deployment timeout after ${maxIterations} iterations`);
1255
+ throw new Error(
1256
+ `monitorReadyRunner timeout: ${deploymentId} did not become Ready within ${maxIterations}*${delayMs}ms`,
1173
1257
  );
1174
- return result;
1175
1258
  },
1176
1259
 
1177
1260
  /**
@@ -1331,6 +1414,34 @@ ${renderHosts}`,
1331
1414
  return undefined;
1332
1415
  },
1333
1416
 
1417
+ /**
1418
+ * Extracts a non-standard `imagePullPolicy` key from an env-resolved
1419
+ * instance lifecycle block (the convention used in `conf.instances.json`,
1420
+ * where `imagePullPolicy` sits alongside `postStart`/`preStop` for
1421
+ * per-instance ergonomics) and returns a clean lifecycle hash that is
1422
+ * safe to splice into the K8S container spec.
1423
+ *
1424
+ * Returns `{ lifecycle, imagePullPolicy }`:
1425
+ * - `lifecycle` — the input minus `imagePullPolicy`, or `undefined` when
1426
+ * the resulting block is empty.
1427
+ * - `imagePullPolicy` — the extracted value, or `undefined` if absent.
1428
+ *
1429
+ * @param {object|undefined} lifecycle - Env-resolved lifecycle block
1430
+ * (already passed through pickEnv). May be `undefined`.
1431
+ * @returns {{ lifecycle: (object|undefined), imagePullPolicy: (string|undefined) }}
1432
+ * @memberof UnderpostDeploy
1433
+ */
1434
+ extractInstanceImagePullPolicy(lifecycle) {
1435
+ if (!lifecycle || typeof lifecycle !== 'object' || !('imagePullPolicy' in lifecycle)) {
1436
+ return { lifecycle, imagePullPolicy: undefined };
1437
+ }
1438
+ const { imagePullPolicy, ...rest } = lifecycle;
1439
+ return {
1440
+ lifecycle: Object.keys(rest).length > 0 ? rest : undefined,
1441
+ imagePullPolicy,
1442
+ };
1443
+ },
1444
+
1334
1445
  /**
1335
1446
  * Generates timeout flags string for deployment commands.
1336
1447
  * @param {object} options - Options containing timeout settings.