@underpostnet/cyberia 3.3.0 → 3.3.76

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 (568) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +17 -5
  3. package/.github/workflows/coverall.cyberia.ci.yml +39 -14
  4. package/.github/workflows/cyberia-client.cd.yml +5 -0
  5. package/.github/workflows/cyberia-server.cd.yml +5 -0
  6. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  7. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  8. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  9. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  10. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  11. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  12. package/.github/workflows/engine-cyberia.cd.yml +3 -0
  13. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  14. package/.github/workflows/ghpkg.ci.yml +35 -20
  15. package/.github/workflows/hardhat.ci.yml +12 -11
  16. package/.github/workflows/npmpkg.ci.yml +17 -15
  17. package/.github/workflows/publish.cyberia.ci.yml +44 -0
  18. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  19. package/.github/workflows/release.cd.yml +1 -0
  20. package/.prettierignore +1 -0
  21. package/AGENTS.md +96 -0
  22. package/CHANGELOG.md +653 -2513
  23. package/CLI-HELP.md +323 -157
  24. package/Dockerfile +25 -9
  25. package/Dockerfile.dev +25 -9
  26. package/Dockerfile.test +5 -5
  27. package/README.md +48 -28
  28. package/bin/build.js +86 -41
  29. package/bin/build.template.js +8 -3
  30. package/bin/cyberia.js +1494 -1403
  31. package/bin/deploy.js +18 -104
  32. package/bin/index.js +1494 -1403
  33. package/compose.env +17 -5
  34. package/conf.js +98 -7
  35. package/deploy/cyberia-client/deploy.sh +46 -0
  36. package/deploy/cyberia-client/package.sh +17 -0
  37. package/deploy/cyberia-client/state.sh +15 -0
  38. package/deploy/cyberia-server/deploy.sh +46 -0
  39. package/deploy/cyberia-server/package.sh +17 -0
  40. package/deploy/cyberia-server/state.sh +15 -0
  41. package/deploy/dd-cyberia/deploy.sh +9 -29
  42. package/deploy/dd-cyberia/init.sh +38 -45
  43. package/deploy/dd-cyberia/package.sh +16 -0
  44. package/deploy/dd-cyberia/state.sh +14 -0
  45. package/deploy/dd-cyberia/sync-deploy.sh +133 -147
  46. package/deploy/lib/config.sh +29 -0
  47. package/deploy/lib/github-actions-logging.sh +610 -0
  48. package/deploy/lib/host.sh +194 -0
  49. package/deploy/lib/state.sh +65 -0
  50. package/deploy/pwa-microservices-template/deploy.sh +17 -42
  51. package/deploy/release/deploy.sh +9 -41
  52. package/deployment.yaml +7 -2
  53. package/docker-compose.yml +23 -17
  54. package/examples/static-page/README.md +19 -19
  55. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  56. package/hardhat/hardhat.config.js +1 -6
  57. package/hardhat/package-lock.json +101 -40
  58. package/hardhat/package.json +2 -2
  59. package/manifests/alertmanager/deployment.yaml +81 -0
  60. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  61. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
  62. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
  63. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  64. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  65. package/manifests/deployment/mongo-express/deployment.yaml +46 -27
  66. package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
  67. package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
  68. package/manifests/deployment/mongo-express/service.yaml +16 -0
  69. package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
  70. package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
  71. package/manifests/grafana/deployment.yaml +26 -7
  72. package/manifests/grafana/kustomization.yaml +1 -0
  73. package/manifests/grafana/service.yaml +6 -1
  74. package/manifests/mariadb/pv.yaml +1 -0
  75. package/manifests/mongodb/statefulset.yaml +9 -2
  76. package/manifests/mysql/pv-pvc.yaml +14 -1
  77. package/manifests/postgresql/pv.yaml +12 -1
  78. package/manifests/postgresql/pvc.yaml +1 -0
  79. package/manifests/prometheus/deployment.yaml +18 -22
  80. package/package.json +87 -12
  81. package/scripts/event-monitor.sh +56 -0
  82. package/scripts/k3s-node-setup.sh +27 -14
  83. package/scripts/kubeadm-node-setup.sh +31 -11
  84. package/scripts/maas-setup.sh +8 -8
  85. package/scripts/selinux-normalize.sh +907 -0
  86. package/scripts/shutdown-machine.sh +843 -0
  87. package/scripts/test-monitor.sh +5 -5
  88. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +15 -10
  89. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
  90. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +7 -2
  91. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +90 -186
  92. package/src/api/core/core.controller.js +1 -1
  93. package/src/api/core/core.router.js +2 -2
  94. package/src/api/core/core.service.js +2 -2
  95. package/src/api/crypto/crypto.controller.js +1 -1
  96. package/src/api/crypto/crypto.service.js +1 -1
  97. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  98. package/src/api/cyberia-action/cyberia-action.router.js +3 -3
  99. package/src/api/cyberia-action/cyberia-action.service.js +5 -6
  100. package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
  101. package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
  102. package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
  103. package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
  104. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +2 -4
  105. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
  106. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +13 -35
  107. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +17 -34
  108. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  109. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
  110. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
  111. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  112. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  113. package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
  114. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  115. package/src/api/cyberia-entity/cyberia-entity.service.js +3 -3
  116. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
  117. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
  118. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -2
  119. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +468 -5
  120. package/src/api/cyberia-instance/cyberia-fallback-capture.js +502 -0
  121. package/src/api/cyberia-instance/cyberia-fallback-world.js +29 -40
  122. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
  123. package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
  124. package/src/api/cyberia-instance/cyberia-instance-map.service.js +35 -142
  125. package/src/api/cyberia-instance/cyberia-instance.controller.js +2 -5
  126. package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
  127. package/src/api/cyberia-instance/cyberia-instance.router.js +5 -18
  128. package/src/api/cyberia-instance/cyberia-instance.service.js +5 -45
  129. package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
  130. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  131. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
  132. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  133. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +76 -3
  134. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  135. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  136. package/src/api/cyberia-map/cyberia-map.service.js +8 -4
  137. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
  138. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
  139. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
  140. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
  141. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  142. package/src/api/cyberia-quest/cyberia-quest.router.js +4 -4
  143. package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
  144. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  145. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
  146. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  147. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  148. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  149. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  150. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  151. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -214
  152. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  153. package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
  154. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  155. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  156. package/src/api/default/default.controller.js +1 -1
  157. package/src/api/default/default.router.js +1 -1
  158. package/src/api/default/default.service.js +2 -2
  159. package/src/api/document/document.controller.js +1 -1
  160. package/src/api/document/document.router.js +1 -1
  161. package/src/api/document/document.service.js +2 -2
  162. package/src/api/file/file.controller.js +1 -1
  163. package/src/api/file/file.ref.js +153 -0
  164. package/src/api/file/file.ref.json +11 -2
  165. package/src/api/file/file.router.js +1 -1
  166. package/src/api/file/file.service.js +2 -2
  167. package/src/api/instance/instance.controller.js +1 -1
  168. package/src/api/instance/instance.router.js +1 -1
  169. package/src/api/instance/instance.service.js +2 -2
  170. package/src/api/ipfs/ipfs.controller.js +1 -1
  171. package/src/api/ipfs/ipfs.router.js +2 -2
  172. package/src/api/ipfs/ipfs.service.js +2 -2
  173. package/src/api/object-layer/object-layer.controller.js +1 -1
  174. package/src/api/object-layer/object-layer.model.js +47 -12
  175. package/src/api/object-layer/object-layer.router.js +12 -5
  176. package/src/api/object-layer/object-layer.service.js +116 -123
  177. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  178. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  179. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  180. package/src/api/test/test.controller.js +1 -1
  181. package/src/api/test/test.service.js +1 -1
  182. package/src/api/user/guest.service.js +3 -3
  183. package/src/api/user/user.controller.js +1 -1
  184. package/src/api/user/user.router.js +2 -2
  185. package/src/api/user/user.service.js +4 -4
  186. package/src/api.js +5 -9
  187. package/src/cli/app.js +402 -0
  188. package/src/cli/baremetal.js +30 -35
  189. package/src/cli/client.js +306 -0
  190. package/src/cli/cloud-init.js +3 -3
  191. package/src/cli/cluster.js +191 -82
  192. package/src/cli/db.js +120 -68
  193. package/src/cli/deploy.js +157 -75
  194. package/src/cli/docker-compose.js +5 -5
  195. package/src/cli/domains.js +184 -0
  196. package/src/cli/dotenv-store.js +143 -0
  197. package/src/cli/event.js +2281 -0
  198. package/src/cli/fs-selection.js +115 -0
  199. package/src/cli/fs.js +159 -343
  200. package/src/cli/host.js +672 -0
  201. package/src/cli/image.js +4 -6
  202. package/src/cli/index.js +343 -151
  203. package/src/cli/ipfs.js +34 -30
  204. package/src/cli/kickstart.js +1 -1
  205. package/src/cli/kubectl.js +218 -41
  206. package/src/cli/lxd.js +3 -3
  207. package/src/cli/monitor.js +1359 -26
  208. package/src/cli/package.js +90 -0
  209. package/src/cli/release.js +16 -12
  210. package/src/cli/repository.js +586 -363
  211. package/src/cli/run.js +398 -843
  212. package/src/cli/secrets.js +2158 -964
  213. package/src/cli/ssh.js +478 -279
  214. package/src/cli/state.js +394 -0
  215. package/src/cli/static.js +2 -2
  216. package/src/cli/system.js +1 -1
  217. package/src/cli/test.js +203 -125
  218. package/src/cli/vultr.js +61 -21
  219. package/src/cli/wireguard.js +1112 -306
  220. package/src/client/components/core/CalendarCore.js +53 -96
  221. package/src/client/components/core/Docs.js +327 -303
  222. package/src/client/components/core/FileExplorer.js +0 -21
  223. package/src/client/components/core/Modal.js +56 -1
  224. package/src/client/components/core/PanelForm.js +4 -4
  225. package/src/client/components/core/Repository.js +56 -0
  226. package/src/client/components/core/Translate.js +7 -0
  227. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  228. package/src/client/components/core/Wallet.js +0 -11
  229. package/src/client/components/core/Worker.js +7 -1
  230. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  231. package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
  232. package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
  233. package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
  234. package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
  235. package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
  236. package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
  237. package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
  238. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
  239. package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
  240. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -35
  241. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
  242. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
  243. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  244. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
  245. package/src/client/components/default/AppShellDefault.js +1 -1
  246. package/src/client/components/default/SettingsDefault.js +2 -2
  247. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  248. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  249. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  250. package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
  251. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +313 -30
  252. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
  253. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
  254. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
  255. package/src/client/public/cyberia-docs/CYBERIA.md +48 -28
  256. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
  257. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  258. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  259. package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
  260. package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
  261. package/src/client/public/default/android-chrome-144x144.png +0 -0
  262. package/src/client/public/default/android-chrome-192x192.png +0 -0
  263. package/src/client/public/default/android-chrome-256x256.png +0 -0
  264. package/src/client/public/default/android-chrome-36x36.png +0 -0
  265. package/src/client/public/default/android-chrome-384x384.png +0 -0
  266. package/src/client/public/default/android-chrome-48x48.png +0 -0
  267. package/src/client/public/default/android-chrome-512x512.png +0 -0
  268. package/src/client/public/default/android-chrome-72x72.png +0 -0
  269. package/src/client/public/default/android-chrome-96x96.png +0 -0
  270. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  271. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  272. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  273. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  274. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  275. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  276. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  277. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  278. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  279. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  280. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  281. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  282. package/src/client/public/default/apple-touch-icon.png +0 -0
  283. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  284. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  285. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  286. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  287. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  288. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  289. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  290. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  291. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  292. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  293. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  294. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  295. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  296. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  297. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  298. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  299. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  300. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  301. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  302. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  303. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  304. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  305. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  306. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  307. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  308. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  309. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  310. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  311. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  312. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  313. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  314. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  315. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  316. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  317. package/src/client/public/default/assets/background/white.jpg +0 -0
  318. package/src/client/public/default/browserconfig.xml +1 -1
  319. package/src/client/public/default/favicon-16x16.png +0 -0
  320. package/src/client/public/default/favicon-32x32.png +0 -0
  321. package/src/client/public/default/favicon-48x48.png +0 -0
  322. package/src/client/public/default/favicon.ico +0 -0
  323. package/src/client/public/default/manifest.webmanifest +5 -5
  324. package/src/client/public/default/mstile-144x144.png +0 -0
  325. package/src/client/public/default/mstile-150x150.png +0 -0
  326. package/src/client/public/default/mstile-310x150.png +0 -0
  327. package/src/client/public/default/mstile-310x310.png +0 -0
  328. package/src/client/public/default/mstile-70x70.png +0 -0
  329. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  330. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  331. package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
  332. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
  333. package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
  334. package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
  335. package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
  336. package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
  337. package/src/client/services/object-layer/object-layer.management.js +6 -10
  338. package/src/client/services/object-layer/object-layer.service.js +3 -1
  339. package/src/client/ssr/RootDocument.js +1 -1
  340. package/src/client/ssr/body/404.js +1 -1
  341. package/src/client/ssr/body/500.js +1 -1
  342. package/src/client/ssr/body/CacheControl.js +1 -1
  343. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  344. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  345. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  346. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  347. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  348. package/src/client/ssr/head/Css.js +1 -1
  349. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  350. package/src/client/ssr/head/DefaultScripts.js +1 -1
  351. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  352. package/src/client/ssr/head/Microdata.js +1 -1
  353. package/src/client/ssr/head/Production.js +1 -1
  354. package/src/client/ssr/head/Pwa.js +1 -1
  355. package/src/client/ssr/head/PwaItemledger.js +1 -1
  356. package/src/client/ssr/head/Seo.js +1 -1
  357. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  358. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  359. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  360. package/src/client/ssr/views/Cyberia404.js +7 -5
  361. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  362. package/src/client/ssr/views/Maintenance.js +1 -1
  363. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  364. package/src/client/ssr/views/Test.js +1 -1
  365. package/src/client/sw/core.sw.js +20 -14
  366. package/src/client-builder/client-build-docs.js +92 -77
  367. package/src/client-builder/client-build-live.js +2 -2
  368. package/src/client-builder/client-build.js +105 -74
  369. package/src/client-builder/client-bundle.js +347 -0
  370. package/src/client-builder/client-dev-server.js +3 -3
  371. package/src/client-builder/client-icons.js +2 -2
  372. package/src/client-builder/ssr.js +3 -3
  373. package/src/client.build.js +3 -6
  374. package/src/client.dev.js +3 -6
  375. package/src/db/DataBaseProvider.js +186 -3
  376. package/src/db/mariadb/MariaDB.js +3 -2
  377. package/src/db/mongo/MongoBootstrap.js +273 -101
  378. package/src/db/mongo/MongoExpress.js +187 -0
  379. package/src/db/mongo/MongooseDB.js +7 -8
  380. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  381. package/src/grpc/cyberia/grpc-server.js +6 -8
  382. package/src/index.js +79 -23
  383. package/src/mailer/EmailRender.js +2 -2
  384. package/src/mailer/MailerInterceptor.js +87 -0
  385. package/src/mailer/MailerProvider.js +50 -6
  386. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +144 -147
  387. package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
  388. package/src/projects/cyberia/besu-genesis-generator.js +8 -17
  389. package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
  390. package/src/projects/cyberia/catalog-cyberia.js +54 -10
  391. package/src/projects/cyberia/gemini-client.js +4 -4
  392. package/src/projects/cyberia/generate-saga.js +5 -12
  393. package/src/projects/cyberia/hot-reload-trigger.js +18 -29
  394. package/src/projects/cyberia/instance-backup.js +210 -0
  395. package/src/projects/cyberia/instance-data.js +178 -258
  396. package/src/projects/cyberia/ipfs-client.js +4 -4
  397. package/src/projects/cyberia/map-preview-generator.js +33 -69
  398. package/src/projects/cyberia/object-layer.js +153 -320
  399. package/src/projects/cyberia/seed-audio.js +139 -0
  400. package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
  401. package/src/projects/cyberia/semantic-layer-generator.js +3 -19
  402. package/src/projects/cyberia/stat-balance.js +81 -0
  403. package/src/projects/cyberia/stat-commands.js +23 -0
  404. package/src/projects/cyberia/stat-contract-generator.js +101 -0
  405. package/src/projects/underpost/catalog-underpost.js +9 -1
  406. package/src/proxy.js +4 -7
  407. package/src/runtime/cyberia-client/Dockerfile +17 -8
  408. package/src/runtime/cyberia-client/Dockerfile.dev +13 -4
  409. package/src/runtime/cyberia-server/Dockerfile +18 -6
  410. package/src/runtime/cyberia-server/Dockerfile.dev +16 -3
  411. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  412. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  413. package/src/runtime/engine-cyberia/Dockerfile.test +5 -5
  414. package/src/runtime/engine-cyberia/compose.env +17 -5
  415. package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
  416. package/src/runtime/express/Express.js +32 -27
  417. package/src/runtime/lampp/Lampp.js +22 -70
  418. package/src/runtime/nginx/Nginx.js +1 -1
  419. package/src/runtime/wp/Wp.js +16 -48
  420. package/src/server/{catalog.js → build/catalog.js} +15 -5
  421. package/src/server/build/coverage.js +188 -0
  422. package/src/server/build/execution.js +402 -0
  423. package/src/server/build/package.js +508 -0
  424. package/src/server/build/testing.js +578 -0
  425. package/src/server/{dns.js → network/dns.js} +144 -11
  426. package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
  427. package/src/server/{middlewares.js → network/middlewares.js} +11 -5
  428. package/src/server/network/node-capability.js +98 -0
  429. package/src/server/{peer.js → network/peer.js} +3 -3
  430. package/src/server/{proxy.js → network/proxy.js} +7 -13
  431. package/src/server/network/router.js +356 -0
  432. package/src/server/{tls.js → network/tls.js} +2 -2
  433. package/src/server/{underpost-compression.js → network/underpost-compression.js} +1 -1
  434. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
  435. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
  436. package/src/server/{cri.js → ops/cri.js} +2 -2
  437. package/src/server/{cron.js → ops/cron.js} +349 -74
  438. package/src/server/ops/event-notification.js +284 -0
  439. package/src/server/{logger.js → ops/logger.js} +143 -23
  440. package/src/server/ops/monitoring.js +1724 -0
  441. package/src/server/{systemd.js → ops/systemd.js} +55 -1
  442. package/src/server/{conf.js → runtime/conf.js} +516 -423
  443. package/src/server/runtime/config-scope.js +215 -0
  444. package/src/server/runtime/environment.js +149 -0
  445. package/src/server/{process.js → runtime/process.js} +153 -12
  446. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  447. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  448. package/src/server/{start.js → runtime/start.js} +128 -39
  449. package/src/server/{auth.js → security/auth.js} +7 -8
  450. package/src/server/security/container-storage.js +382 -0
  451. package/src/server/{crypto.js → security/crypto.js} +1 -1
  452. package/src/server/{selinux.js → security/selinux.js} +1 -1
  453. package/src/server/{backup.js → storage/backup.js} +17 -8
  454. package/src/server/{data-query.js → storage/data-query.js} +17 -1
  455. package/src/server/storage/downloader.js +121 -0
  456. package/src/server/storage/repository.js +68 -0
  457. package/src/server/storage/zip.js +153 -0
  458. package/src/server.js +4 -7
  459. package/src/ws/IoInterface.js +1 -1
  460. package/src/ws/IoServer.js +1 -1
  461. package/src/ws/core/core.ws.connection.js +1 -1
  462. package/src/ws/core/core.ws.emit.js +1 -1
  463. package/src/ws/core/core.ws.server.js +1 -1
  464. package/src/ws/default/default.ws.connection.js +1 -1
  465. package/src/ws/default/default.ws.emit.js +1 -1
  466. package/src/ws/default/default.ws.server.js +1 -1
  467. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  468. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  469. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  470. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  471. package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
  472. package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
  473. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +64 -0
  474. package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
  475. package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
  476. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +17 -23
  477. package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
  478. package/test/integration/app/cyberia/cyberia-load.test.js +466 -0
  479. package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
  480. package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
  481. package/test/integration/app/cyberia/fallback-world-capture.test.js +338 -0
  482. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  483. package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
  484. package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
  485. package/test/integration/app/cyberia/seed-audio.test.js +275 -0
  486. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  487. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  488. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  489. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  490. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  491. package/test/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
  492. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  493. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  494. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  495. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  496. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  497. package/test/integration/infra/2-network/wireguard-cli.test.js +1187 -0
  498. package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +649 -55
  499. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  500. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  501. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  502. package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
  503. package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
  504. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  505. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  506. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  507. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +6 -6
  508. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -4
  509. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  510. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  511. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  512. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  513. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  514. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  515. package/test/support/shell-harness.js +73 -0
  516. package/test/unit/build-template.test.js +97 -0
  517. package/test/unit/build-workflow-offline.test.js +132 -0
  518. package/test/unit/catalog.test.js +71 -0
  519. package/test/unit/client-build-docs.test.js +361 -0
  520. package/test/unit/client-bundle.test.js +313 -0
  521. package/test/unit/conf-loading.test.js +303 -0
  522. package/test/unit/conf-resolution.test.js +996 -0
  523. package/test/unit/coverage-artifact.test.js +221 -0
  524. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  525. package/test/unit/cyberia/instance-backup.test.js +183 -0
  526. package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
  527. package/test/unit/cyberia/publish-workflow.test.js +22 -0
  528. package/test/unit/cyberia/stat-balance.test.js +69 -0
  529. package/test/unit/deploy-env-resolution.test.js +38 -0
  530. package/test/unit/deploy-log-table.test.js +518 -0
  531. package/test/unit/downloader-integrity.test.js +98 -0
  532. package/test/unit/execution-profiles.test.js +219 -0
  533. package/test/unit/file-reference-registry.test.js +141 -0
  534. package/test/unit/fleet-sync-source.test.js +149 -0
  535. package/test/unit/fs-storage-paths.test.js +596 -0
  536. package/test/unit/logger-redaction.test.js +141 -0
  537. package/test/unit/package.test.js +457 -0
  538. package/test/unit/prepare-host.test.js +382 -0
  539. package/test/unit/process-environment.test.js +18 -0
  540. package/test/unit/propagation-message.test.js +78 -0
  541. package/test/unit/redeploy-plan.test.js +24 -0
  542. package/test/unit/release-bump.test.js +474 -0
  543. package/test/unit/ssh-output-redaction.test.js +28 -0
  544. package/test/unit/start-options.test.js +46 -0
  545. package/test/unit/test-tiers.test.js +220 -0
  546. package/test/unit/zip-archive.test.js +142 -0
  547. package/vitest.config.js +66 -0
  548. package/.nycrc +0 -9
  549. package/deploy/lib/logging.sh +0 -96
  550. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  551. package/manifests/mongodb/pv-pvc.yaml +0 -59
  552. package/scripts/coverall-test-cyberia.sh +0 -24
  553. package/scripts/coverall-test.sh +0 -24
  554. package/scripts/link-local-underpost-cli.sh +0 -6
  555. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
  556. package/src/api/user/user.build.js +0 -16
  557. package/src/cli/env.js +0 -177
  558. package/src/client/components/core/Blockchain.js +0 -41
  559. package/src/client/components/core/Blog.js +0 -9
  560. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  561. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
  562. package/src/client/public/default/assets/background/dark.jpg +0 -0
  563. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  564. package/src/client/public/default/assets/background/white0.jpg +0 -0
  565. package/src/client/public/doc/favicon.ico +0 -0
  566. package/src/client/public/doc/sitemap +0 -148
  567. package/src/server/downloader.js +0 -73
  568. package/src/server/environment.js +0 -98
@@ -0,0 +1,394 @@
1
+ /**
2
+ * State domain: the runtime monitoring / telemetry layer.
3
+ *
4
+ * An agent that observes one workload's live container execution state, health indicators and
5
+ * performance metrics, and exports them off-cluster. Its base module is
6
+ * {@link module:src/server/runtime/runtime-status.js}, which defines the observation contract;
7
+ * this domain is the operator surface over it.
8
+ *
9
+ * Backed by its own store file, never the host configuration store. The two have different
10
+ * lifetimes and different owners: host configuration is provisioned onto a node and survives,
11
+ * while this is per-container and resets with the container. Sharing one file meant a host
12
+ * operation could erase a workload's status, and a status write could outlive the workload that
13
+ * produced it.
14
+ *
15
+ * The domain has **no durable source**, and that is what makes it the fourth domain rather than
16
+ * a variation on the other three. An observation is only ever true of a running container, so:
17
+ * - `load` collects from the live workload rather than from a file,
18
+ * - `publish` exports the collection off-cluster rather than writing a source back,
19
+ * - `apply` stamps a contract phase into the live workload.
20
+ * That asymmetry is deliberate and is the whole of this domain.
21
+ *
22
+ * Implements the canonical domain action set; see {@link UnderpostDomains.DOMAIN_ACTIONS}.
23
+ * @module src/cli/state.js
24
+ * @namespace UnderpostState
25
+ */
26
+
27
+ import fs from 'fs-extra';
28
+
29
+ import { domainContextFactory } from './domains.js';
30
+ import { dotenvStoreFactory } from './dotenv-store.js';
31
+ import { getUnderpostRootPath, isOciRuntime } from '../server/runtime/environment.js';
32
+ import { loggerFactory } from '../server/ops/logger.js';
33
+ import {
34
+ CONTAINER_STATUS_KEY,
35
+ containerStatusValue,
36
+ deployStatusPort,
37
+ normalizeContainerStatus,
38
+ RUNTIME_STATUS,
39
+ runtimeTelemetryPayload,
40
+ setRuntimeStatus,
41
+ } from '../server/runtime/runtime-status.js';
42
+ import Underpost from '../index.js';
43
+
44
+ const logger = loggerFactory(import.meta);
45
+
46
+ const store = dotenvStoreFactory({
47
+ path: () => `${getUnderpostRootPath()}/.state`,
48
+ label: 'container state',
49
+ });
50
+
51
+ /**
52
+ * The workload this invocation observes: `<deployId>[-<instanceId>]-<env>`, the same name every
53
+ * other object of that workload is prefixed with.
54
+ * @param {object} context - Normalized domain context.
55
+ * @returns {string} Workload id.
56
+ * @memberof UnderpostState
57
+ */
58
+ const deployIdOf = (context = {}) =>
59
+ `${context.args?.['deploy-id'] ?? ''}`.trim() || `${process.env.DEPLOY_ID || ''}`.trim();
60
+
61
+ const workloadId = (context = {}) =>
62
+ [deployIdOf(context), `${context.args?.['instance-id'] ?? ''}`.trim()].filter(Boolean).join('-');
63
+
64
+ /**
65
+ * Whether this process is reporting into a GitHub Actions job.
66
+ *
67
+ * `GITHUB_ACTIONS` exists on a runner but is not carried across the SSH hop a remote deploy
68
+ * runs over, so `RUN_QUIET_CI` — which the deploy workflows export explicitly — is what actually
69
+ * marks the far side. Both are honoured, and `deploy/lib/github-actions-logging.sh` reads the same pair.
70
+ * @returns {boolean} True when workflow commands will be interpreted.
71
+ * @memberof UnderpostState
72
+ */
73
+ const inGithubActions = () => Boolean(process.env.GITHUB_ACTIONS || process.env.RUN_QUIET_CI);
74
+
75
+ /**
76
+ * Renders one observation as GitHub Actions workflow commands on stdout.
77
+ *
78
+ * stdout is the only transport that survives the SSH hop: `$GITHUB_OUTPUT` and
79
+ * `$GITHUB_STEP_SUMMARY` are files on the runner, so they are written too when they exist —
80
+ * a direct runner invocation — but never relied on.
81
+ * @param {object} observation - Telemetry observation.
82
+ * @memberof UnderpostState
83
+ */
84
+ const exportToGithubActions = (observation) => {
85
+ const { workload, status, ready, phase } = observation;
86
+ const summary =
87
+ `${workload || 'workload'} | status=${status ?? 'unknown'} | ready=${ready} | ` +
88
+ `uptime=${observation.metrics?.uptimeSeconds ?? '?'}s | rss=${Math.round(
89
+ (observation.metrics?.rssBytes ?? 0) / 1048576,
90
+ )}MiB`;
91
+ // A fatal phase is an annotation the job surfaces, not a line in a log nobody opens.
92
+ console.log(`::${phase === RUNTIME_STATUS.ERROR ? 'error' : 'notice'} title=underpost state::${summary}`);
93
+ console.log(`::group::underpost state ${workload || ''}`.trimEnd());
94
+ console.log(JSON.stringify(observation, null, 2));
95
+ console.log('::endgroup::');
96
+ const appendFile = (variable, content) => {
97
+ const target = process.env[variable];
98
+ if (!target) return;
99
+ try {
100
+ fs.appendFileSync(target, content);
101
+ } catch (error) {
102
+ logger.warn(`[state] could not write ${variable}`, error?.message ?? error);
103
+ }
104
+ };
105
+ appendFile('GITHUB_OUTPUT', `status=${status ?? ''}\nready=${ready}\nworkload=${workload ?? ''}\n`);
106
+ appendFile('GITHUB_STEP_SUMMARY', `### underpost state\n\n\`\`\`\n${summary}\n\`\`\`\n`);
107
+ };
108
+
109
+ /**
110
+ * @class UnderpostState
111
+ * @description Runtime monitoring / telemetry domain, and key-level access to its store.
112
+ * @memberof UnderpostState
113
+ */
114
+ class UnderpostState {
115
+ static API = {
116
+ ...store,
117
+
118
+ /**
119
+ * Whether this process runs inside a container, by Kubernetes service injection or Docker's
120
+ * marker file. Kept on this class because every caller reaches it through the state domain;
121
+ * the detection itself is {@link ServerEnvironment.isOciRuntime}, shared with the OCI env
122
+ * overlay so both agree on what "inside a container" means.
123
+ * @returns {boolean} True when running inside a container.
124
+ * @memberof UnderpostState
125
+ */
126
+ isInsideContainer() {
127
+ return isOciRuntime();
128
+ },
129
+
130
+ /**
131
+ * The current observation: execution state, health indicators and performance metrics.
132
+ *
133
+ * In-pod this is measured directly. On a node it is collected from the workload's pods over
134
+ * the monitor's own exec transport, so there is one implementation of "read a pod's status"
135
+ * and the agent can never disagree with the monitor that gates the rollout.
136
+ * @param {object} [context] - Normalized domain context.
137
+ * @returns {object} Telemetry observation.
138
+ * @memberof UnderpostState
139
+ */
140
+ observe(context = {}) {
141
+ const workload = workloadId(context);
142
+ const local = runtimeTelemetryPayload();
143
+ if (UnderpostState.API.isInsideContainer() || !workload)
144
+ return { workload: workload || local.deployId, phase: local.status, ...local, pods: null };
145
+ const pods = Underpost.kubectl
146
+ .get(`${workload}-${context.env}`, 'pods', context.namespace)
147
+ .map((pod) => pod.NAME)
148
+ .filter(Boolean);
149
+ // Status gates the rollout and must stay total; telemetry adds the fields that exist only
150
+ // where the process is measured. A pod that cannot answer the second keeps the first.
151
+ const internalPort = deployStatusPort(deployIdOf(context), context.env);
152
+ const readings = pods.map((pod) => {
153
+ const status = Underpost.monitor.readRuntimeStatusViaExec(pod, context.namespace);
154
+ const telemetry = Underpost.monitor.readRuntimeTelemetryViaExec(pod, context.namespace, internalPort);
155
+ return {
156
+ pod,
157
+ ...status,
158
+ health: telemetry.ok ? (telemetry.telemetry?.health ?? null) : null,
159
+ metrics: telemetry.ok ? (telemetry.telemetry?.metrics ?? null) : null,
160
+ telemetryError: telemetry.ok ? undefined : telemetry.transportError,
161
+ };
162
+ });
163
+ // The workload's phase is its worst reading: one pod latched `error` is the deployment's
164
+ // state, not an outlier to be averaged away.
165
+ const statuses = readings.filter((reading) => reading.ok).map((reading) => reading.status);
166
+ const phase = statuses.includes(RUNTIME_STATUS.ERROR)
167
+ ? RUNTIME_STATUS.ERROR
168
+ : statuses.every((status) => status === RUNTIME_STATUS.RUNNING) && statuses.length > 0
169
+ ? RUNTIME_STATUS.RUNNING
170
+ : statuses[0];
171
+ return {
172
+ workload,
173
+ env: context.env,
174
+ namespace: context.namespace,
175
+ status: phase ?? null,
176
+ phase: phase ?? null,
177
+ ready: phase === RUNTIME_STATUS.RUNNING,
178
+ pods: readings,
179
+ metrics: { pods: readings.length, reporting: statuses.length },
180
+ observedAt: new Date().toISOString(),
181
+ };
182
+ },
183
+
184
+ // ── canonical domain actions ────────────────────────────────────────────────────────────
185
+
186
+ /**
187
+ * Renders an observation as a fixed-width table, one row per pod.
188
+ *
189
+ * The shape an operator actually watches: JSON is the export format, but a rollout is read
190
+ * by scanning columns. Absent metrics print as `-` rather than collapsing the row, so a pod
191
+ * that answers only the status read still occupies its line.
192
+ * @param {object} observation - The observation to render.
193
+ * @returns {string} The rendered table.
194
+ * @memberof UnderpostState
195
+ */
196
+ table(observation = {}, refresh = '') {
197
+ const mib = (bytes) => (typeof bytes === 'number' ? `${Math.round(bytes / 1048576)}Mi` : '-');
198
+ const columns = [
199
+ ['POD', 42],
200
+ ['PHASE', 26],
201
+ ['READY', 6],
202
+ ['UPTIME', 8],
203
+ ['RSS', 9],
204
+ ['HEAP', 9],
205
+ ['CPU', 10],
206
+ ['LOAD', 6],
207
+ ];
208
+ const pad = (value, width) => `${value ?? '-'}`.slice(0, width).padEnd(width);
209
+ const line = (cells) => `| ${cells.map(([v, w]) => pad(v, w)).join(' | ')} |`;
210
+ const rows = (observation.pods ?? []).map((reading) =>
211
+ line([
212
+ [reading.pod, 42],
213
+ [reading.status ?? reading.transportError ?? '-', 26],
214
+ [reading.health ? (reading.health.ready ? 'yes' : 'no') : '-', 6],
215
+ [reading.metrics ? `${reading.metrics.uptimeSeconds}s` : '-', 8],
216
+ [mib(reading.metrics?.rssBytes), 9],
217
+ [mib(reading.metrics?.heapUsedBytes), 9],
218
+ [reading.metrics ? `${Math.round((reading.metrics.cpuUserMicros ?? 0) / 1000)}ms` : '-', 10],
219
+ [reading.metrics ? `${reading.metrics.loadAverage1m?.toFixed?.(2) ?? '-'}` : '-', 6],
220
+ ]),
221
+ );
222
+ const header = line(columns.map(([name, width]) => [name, width]));
223
+ const rule = `|${columns.map(([, width]) => '-'.repeat(width + 2)).join('|')}|`;
224
+ const clock = new Date().toTimeString().slice(0, 8);
225
+ const title = `Runtime state ${observation.workload ?? 'workload'}${
226
+ refresh ? ` (refresh #${refresh}, ${clock})` : ''
227
+ } | phase=${observation.phase ?? '-'} | pods=${observation.metrics?.pods ?? (observation.pods ?? []).length}`;
228
+ return [title, header, rule, ...(rows.length > 0 ? rows : [line([['(no pods)', 42]])])].join('\n');
229
+ },
230
+
231
+ /**
232
+ * Onboards the agent: confirms the state store is writable, then takes a first observation.
233
+ * Idempotent — repeating it re-observes rather than re-provisioning.
234
+ * @param {object} context - Normalized domain context.
235
+ * @returns {{store: string, workload: string, status: string|null}} What was onboarded.
236
+ * @memberof UnderpostState
237
+ */
238
+ setup(context = {}) {
239
+ context = domainContextFactory(context);
240
+ const storePath = store.path();
241
+ if (context.dryRun) {
242
+ logger.info('[dry-run] state setup would provision the container state store', { store: storePath });
243
+ return { store: storePath, workload: workloadId(context), status: null };
244
+ }
245
+ fs.ensureFileSync(storePath);
246
+ const { status } = UnderpostState.API.load(context);
247
+ return { store: storePath, workload: workloadId(context), status };
248
+ },
249
+
250
+ /**
251
+ * Collects the live observation into this node's state store.
252
+ *
253
+ * The state domain's source is the running workload, not a file, so `load` reads the cluster
254
+ * rather than the disk. What it writes is the collected reading, which is what `publish`
255
+ * then exports.
256
+ * @param {object} context - Normalized domain context.
257
+ * @returns {{workload: string, status: string|null, pods: number}} What was collected.
258
+ * @memberof UnderpostState
259
+ */
260
+ load(context = {}) {
261
+ context = domainContextFactory(context);
262
+ const observation = UnderpostState.API.observe(context);
263
+ const status = normalizeContainerStatus(observation.status) ?? null;
264
+ if (context.dryRun) {
265
+ logger.info('[dry-run] state load would record the observation', {
266
+ workload: observation.workload,
267
+ status,
268
+ });
269
+ return { workload: observation.workload, status, pods: observation.pods?.length ?? 0 };
270
+ }
271
+ if (status) store.set(CONTAINER_STATUS_KEY, containerStatusValue(observation.workload, context.env, status));
272
+ logger.info('Runtime state collected', {
273
+ workload: observation.workload,
274
+ status,
275
+ pods: observation.pods?.length ?? 0,
276
+ });
277
+ return { workload: observation.workload, status, pods: observation.pods?.length ?? 0 };
278
+ },
279
+
280
+ /**
281
+ * Exports the observation off-cluster.
282
+ *
283
+ * The inverse of `load` for the other domains is a write back to the durable source; this
284
+ * domain has none, so the outward direction is the export instead. Under GitHub Actions the
285
+ * observation becomes workflow commands on stdout — the one transport that survives the SSH
286
+ * hop a remote deploy runs over — and, on a runner, `$GITHUB_OUTPUT` and
287
+ * `$GITHUB_STEP_SUMMARY` as well. Anywhere else it is JSON on stdout.
288
+ * @param {object} context - Normalized domain context.
289
+ * @returns {object} The exported observation.
290
+ * @memberof UnderpostState
291
+ */
292
+ publish(context = {}) {
293
+ context = domainContextFactory(context);
294
+ const observation = UnderpostState.API.observe(context);
295
+ if (context.dryRun) {
296
+ logger.info('[dry-run] state publish would export the observation', {
297
+ workload: observation.workload,
298
+ target: inGithubActions() ? 'github-actions' : 'stdout',
299
+ });
300
+ return observation;
301
+ }
302
+ if (inGithubActions()) exportToGithubActions(observation);
303
+ else console.log(JSON.stringify(observation, null, 2));
304
+ return observation;
305
+ },
306
+
307
+ /**
308
+ * Stamps a contract phase into the live runtime.
309
+ *
310
+ * `--args phase=<phase>` selects it, defaulting to the phase already observed, so a bare
311
+ * `state apply` re-asserts what is true rather than inventing a transition. This is the same
312
+ * write the in-pod lifecycle hooks perform, which is why they call the state domain and not
313
+ * the host one.
314
+ * @param {object} context - Normalized domain context.
315
+ * @returns {{workload: string, phase: string}} What was stamped.
316
+ * @memberof UnderpostState
317
+ */
318
+ apply(context = {}) {
319
+ context = domainContextFactory(context);
320
+ const workload = workloadId(context) || `${process.env.DEPLOY_ID || ''}`.trim();
321
+ const requested = `${context.args['phase'] ?? ''}`.trim();
322
+ const phase = requested || UnderpostState.API.observe(context).status || RUNTIME_STATUS.INIT;
323
+ const known = Object.values(RUNTIME_STATUS);
324
+ if (requested && !known.includes(requested))
325
+ throw new Error(`[state] unknown phase: ${requested} (expected ${known.join(', ')})`);
326
+ if (context.dryRun) {
327
+ logger.info('[dry-run] state apply would stamp the runtime phase', { workload, phase });
328
+ return { workload, phase };
329
+ }
330
+ setRuntimeStatus(workload, context.env, phase);
331
+ return { workload, phase };
332
+ },
333
+
334
+ /**
335
+ * Read-only report: the observation, plus where this agent is reading it from.
336
+ * @param {object} context - Normalized domain context.
337
+ * @returns {object} Report.
338
+ * @memberof UnderpostState
339
+ */
340
+ status(context = {}) {
341
+ context = domainContextFactory(context);
342
+ const observation = UnderpostState.API.observe(context);
343
+ const report = {
344
+ domain: 'state',
345
+ env: context.env,
346
+ namespace: context.namespace,
347
+ store: store.path(),
348
+ source: UnderpostState.API.isInsideContainer() ? 'in-container' : 'cluster-exec',
349
+ ...observation,
350
+ };
351
+ console.log(UnderpostState.API.table(observation, `${context.args.refresh ?? ''}`.trim()));
352
+ return report;
353
+ },
354
+
355
+ /**
356
+ * Replaces the current projection: drops the latched status and re-stamps it from a fresh
357
+ * observation. The way out of a fatal latch that outlived the fault that set it.
358
+ * @param {object} context - Normalized domain context.
359
+ * @returns {{workload: string, phase: string}} The re-stamped phase.
360
+ * @memberof UnderpostState
361
+ */
362
+ rotate(context = {}) {
363
+ context = domainContextFactory(context);
364
+ if (context.dryRun) {
365
+ logger.info('[dry-run] state rotate would clear and re-stamp the runtime phase');
366
+ return { workload: workloadId(context), phase: null };
367
+ }
368
+ store.delete(CONTAINER_STATUS_KEY);
369
+ return UnderpostState.API.apply(context);
370
+ },
371
+
372
+ /**
373
+ * Withdraws the agent's local traces: removes the container state store.
374
+ * @param {object} context - Normalized domain context.
375
+ * @returns {{removed: string|null}} What was withdrawn.
376
+ * @memberof UnderpostState
377
+ */
378
+ clean(context = {}) {
379
+ context = domainContextFactory(context);
380
+ const storePath = store.path();
381
+ if (context.dryRun) {
382
+ logger.info('[dry-run] state clean would remove the container state store', { store: storePath });
383
+ return { removed: storePath };
384
+ }
385
+ const existed = fs.existsSync(storePath);
386
+ if (existed) fs.removeSync(storePath);
387
+ logger.info('Container state store withdrawn', { store: existed ? storePath : null });
388
+ return { removed: existed ? storePath : null };
389
+ },
390
+ };
391
+ }
392
+
393
+ export default UnderpostState;
394
+ export { UnderpostState, workloadId };
package/src/cli/static.js CHANGED
@@ -7,10 +7,10 @@ import fs from 'fs-extra';
7
7
  import path from 'path';
8
8
  import express from 'express';
9
9
  import { ssrFactory } from '../client-builder/ssr.js';
10
- import { shellExec } from '../server/process.js';
10
+ import { shellExec } from '../server/runtime/process.js';
11
11
  import Underpost from '../index.js';
12
12
  import { JSONweb } from '../client-builder/client-formatted.js';
13
- import { loggerFactory, loggerMiddleware } from '../server/logger.js';
13
+ import { loggerFactory, loggerMiddleware } from '../server/ops/logger.js';
14
14
  const logger = loggerFactory(import.meta);
15
15
  /**
16
16
  * @typedef {Object} MetadataOptions
package/src/cli/system.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  selinuxPackagesCommandFactory,
14
14
  selinuxSshContextCommandsFactory,
15
15
  shellArgumentFactory,
16
- } from '../server/selinux.js';
16
+ } from '../server/security/selinux.js';
17
17
 
18
18
  /**
19
19
  * @class UnderpostSystemProvisionig