@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
@@ -4,28 +4,34 @@
4
4
  * @namespace UnderpostCluster
5
5
  */
6
6
 
7
- import { clusterTypeFactory, gatewayApiEnabledFactory, resolveReplicaCount } from '../server/conf.js';
8
- import { getNpmRootPath, HOST_VOLUME_ROOT } from '../server/environment.js';
9
- import { loggerFactory } from '../server/logger.js';
10
- import { shellExec } from '../server/process.js';
11
- import { crictlCommandFactory, resolveCriSocket } from '../server/cri.js';
7
+ import { clusterTypeFactory, gatewayApiEnabledFactory, resolveReplicaCount } from '../server/runtime/conf.js';
8
+ import { getNpmRootPath, HOST_VOLUME_ROOT } from '../server/runtime/environment.js';
9
+ import { loggerFactory } from '../server/ops/logger.js';
10
+ import { shellExec } from '../server/runtime/process.js';
11
+ import { crictlCommandFactory, resolveCriSocket } from '../server/ops/cri.js';
12
12
  import {
13
13
  runSELinuxCommands,
14
- selinuxContainerSharedContextCommandsFactory,
15
14
  selinuxEnforcingCommandsFactory,
16
15
  selinuxPackagesCommandFactory,
17
16
  selinuxRestoreconCommandFactory,
18
- } from '../server/selinux.js';
19
- import { UNDERPOST_GATEWAY, seedDefaultStatusPage } from '../server/underpost-gateway.js';
17
+ } from '../server/security/selinux.js';
18
+ import ContainerStorageService, {
19
+ containerStorageRootsFactory,
20
+ ensureContainerStorage,
21
+ localPathConfigCommandFactory,
22
+ localPathRootsFactory,
23
+ } from '../server/security/container-storage.js';
24
+ import { UNDERPOST_GATEWAY, seedDefaultStatusPage } from '../server/network/underpost-gateway.js';
20
25
  import {
21
26
  UNDERPOST_INGRESS,
22
27
  gatewayBackendFactory,
23
28
  underpostIngressConfFactory,
24
29
  underpostIngressHostMapFactory,
25
30
  underpostIngressManifestsFactory,
26
- } from '../server/underpost-ingress.js';
31
+ } from '../server/network/underpost-ingress.js';
27
32
  import { MONGODB_DEFAULT_REPLICA_COUNT } from '../db/mongo/MongooseDB.js';
28
33
  import { MongoBootstrap } from '../db/mongo/MongoBootstrap.js';
34
+ import { MongoExpress } from '../db/mongo/MongoExpress.js';
29
35
  import os from 'os';
30
36
  import fs from 'fs-extra';
31
37
  import Underpost from '../index.js';
@@ -35,8 +41,8 @@ const logger = loggerFactory(import.meta);
35
41
  const GATEWAY_API_RELEASE = 'v1.5.1';
36
42
  const ENVOY_GATEWAY_VERSION = 'v1.8.3';
37
43
  const CONTOUR_NAMESPACE = 'projectcontour';
38
- const KUBEADM_CONTAINER_MOUNT_PATHS = ['/etc/kubernetes', '/var/lib/etcd', '/var/lib/calico'];
39
- const HOST_VOLUME_PATHS = ['/data', '/opt/local-path-provisioner', HOST_VOLUME_ROOT];
44
+ const LOCAL_PATH_PROVISIONER_MANIFEST =
45
+ 'https://cdn.jsdelivr.net/gh/rancher/local-path-provisioner@master/deploy/local-path-storage.yaml';
40
46
  const K3S_SELINUX_PATHS = [
41
47
  '/usr/local/bin/k3s',
42
48
  '/etc/rancher',
@@ -45,15 +51,16 @@ const K3S_SELINUX_PATHS = [
45
51
  '/var/lib/cni',
46
52
  ];
47
53
 
48
- const shareWithContainers = (paths = []) => {
49
- for (const path of paths) shellExec(`sudo mkdir -p ${path}`);
50
- runSELinuxCommands(selinuxContainerSharedContextCommandsFactory(paths), { execute: shellExec });
51
- };
52
-
53
- const enforceSELinux = (paths = []) => {
54
+ // `semanage` and `restorecon` come from separate packages and neither is guaranteed on a minimal
55
+ // Rocky install. Installed before anything tries to register a mapping, because a missing
56
+ // `semanage` would otherwise turn every persistent labeling command into a hard failure.
57
+ const ensureSELinuxTooling = () =>
54
58
  shellExec(
55
59
  `if [ -f /etc/redhat-release ] && command -v dnf >/dev/null 2>&1 && { ! command -v restorecon >/dev/null 2>&1 || ! command -v semanage >/dev/null 2>&1; }; then ${selinuxPackagesCommandFactory()}; fi`,
56
60
  );
61
+
62
+ const enforceSELinux = (paths = []) => {
63
+ ensureSELinuxTooling();
57
64
  const commands = selinuxEnforcingCommandsFactory({ restorePaths: paths });
58
65
  runSELinuxCommands(commands, { execute: shellExec });
59
66
  };
@@ -76,6 +83,7 @@ class UnderpostCluster {
76
83
  * @param {object} [options] - Configuration options for cluster initialization.
77
84
  * @param {boolean} [options.mongodb=false] - Deploy MongoDB.
78
85
  * @param {boolean} [options.mongodb4=false] - Deploy MongoDB 4.4.
86
+ * @param {boolean} [options.mongoExpress=false] - Deploy the mongo-express web client for inspecting the MongoDB StatefulSet collections.
79
87
  * @param {string} [options.serviceHost=''] - Set a custom host/IP for exposed MongoDB and Valkey clients.
80
88
  * @param {boolean} [options.mariadb=false] - Deploy MariaDB.
81
89
  * @param {boolean} [options.mysql=false] - Deploy MySQL.
@@ -112,9 +120,10 @@ class UnderpostCluster {
112
120
  * @param {boolean} [options.nodePort=false] - Expose enabled ready services (e.g. MongoDB 4.4, Valkey)
113
121
  * to the host/public network via their NodePort Service manifest. The node port value lives directly
114
122
  * in each manifest (mongodb-4.4/mongodb-nodeport.yaml, valkey/valkey-nodeport.yaml).
115
- * @param {string} [options.nodeSelector=''] - Pin the just-deployed StatefulSet (MongoDB 4.4 / Valkey)
116
- * to a specific Kubernetes node by name (e.g. 'localhost.localdomain'). Applied via a
117
- * `kubernetes.io/hostname` nodeSelector patch once the workload reports Ready.
123
+ * @param {string} [options.nodeName=''] - Pin the just-deployed StatefulSet (MongoDB 4.4 / Valkey)
124
+ * and the observability workloads to a specific Kubernetes node by name (e.g.
125
+ * 'localhost.localdomain'). Applied via a `kubernetes.io/hostname` nodeSelector patch once
126
+ * the workload reports Ready.
118
127
  * @memberof UnderpostCluster
119
128
  */
120
129
  async init(
@@ -122,6 +131,7 @@ class UnderpostCluster {
122
131
  options = {
123
132
  mongodb: false,
124
133
  mongodb4: false,
134
+ mongoExpress: false,
125
135
  serviceHost: '',
126
136
  mariadb: false,
127
137
  mysql: false,
@@ -154,7 +164,7 @@ class UnderpostCluster {
154
164
  hosts: '',
155
165
  replicas: '',
156
166
  nodePort: false,
157
- nodeSelector: '',
167
+ nodeName: '',
158
168
  },
159
169
  ) {
160
170
  if (options.initHost) return Underpost.cluster.initHost();
@@ -232,6 +242,12 @@ class UnderpostCluster {
232
242
  logger.info(
233
243
  `Detected existing ${runtime.type} cluster (${runtime.ready ? 'Ready' : 'NotReady'}); skipping initialization.`,
234
244
  );
245
+ // Initialization is skipped, but the labeling invariant is not: the node directories
246
+ // backing PersistentVolumes outlive the bring-up that created them, and a policy update,
247
+ // a full relabel or a directory recreated by kubelet resets them to the policy default.
248
+ // Re-asserting it costs a `semanage` lookup and a `restorecon` pass, mutates no workload,
249
+ // and never changes SELinux mode.
250
+ Underpost.cluster.ensureContainerStorageContexts();
235
251
  }
236
252
 
237
253
  // --- Kubeadm/Kind/K3s Cluster Initialization ---
@@ -265,7 +281,7 @@ class UnderpostCluster {
265
281
  } else if (options.kubeadm) {
266
282
  Underpost.cluster.config();
267
283
  Underpost.cluster.natSetup({ underpostRoot });
268
- shareWithContainers([...KUBEADM_CONTAINER_MOUNT_PATHS, ...HOST_VOLUME_PATHS]);
284
+ Underpost.cluster.ensureContainerStorageContexts({ controlPlane: true });
269
285
  logger.info('Initializing Kubeadm control plane...');
270
286
  // Set default values if not provided
271
287
  const podNetworkCidr = options.podNetworkCidr || '192.168.0.0/16';
@@ -293,18 +309,13 @@ class UnderpostCluster {
293
309
  // Untaint control plane node to allow scheduling pods
294
310
  const nodeName = os.hostname();
295
311
  shellExec(`kubectl taint nodes ${nodeName} node-role.kubernetes.io/control-plane:NoSchedule-`);
296
- // Install local-path-provisioner for dynamic PVCs
297
- logger.info('Installing local-path-provisioner...');
298
- shellExec(
299
- `kubectl apply -f https://cdn.jsdelivr.net/gh/rancher/local-path-provisioner@master/deploy/local-path-storage.yaml`,
300
- );
301
-
302
312
  // The CNI lands asynchronously, and the node stays NotReady until it
303
313
  // does. Block here so the deploy steps that follow (MongoDB and the
304
314
  // application workloads) schedule onto a node that can actually run
305
315
  // them, instead of racing the Calico rollout.
306
316
  logger.info('Waiting for the node to become Ready (Calico rollout)...');
307
317
  shellExec(`kubectl wait --for=condition=Ready node --all --timeout=300s`);
318
+ Underpost.cluster.ensureLocalPathProvisioner();
308
319
  } else {
309
320
  Underpost.cluster.config();
310
321
  Underpost.cluster.natSetup({ underpostRoot });
@@ -355,36 +366,19 @@ class UnderpostCluster {
355
366
  shellExec(`node ${underpostRoot}/bin/deploy kubeflow-spark-operator${options.kubeadm ? ' kubeadm' : ''}`);
356
367
  }
357
368
 
358
- if (options.grafana) {
359
- shellExec(`kubectl delete deployment grafana -n ${options.namespace} --ignore-not-found`);
360
- shellExec(`kubectl apply -k ${underpostRoot}/manifests/grafana -n ${options.namespace}`);
361
- const yaml = `${fs
362
- .readFileSync(`${underpostRoot}/manifests/grafana/deployment.yaml`, 'utf8')
363
- .replace('{{GF_SERVER_ROOT_URL}}', options.hosts.split(',')[0])}`;
364
- console.log(yaml);
365
- shellExec(`kubectl apply -f - -n ${options.namespace} <<'EOF'
366
- ${yaml}
367
- EOF
368
- `);
369
- }
370
-
371
- if (options.prom) {
372
- shellExec(`kubectl delete deployment prometheus --ignore-not-found`);
373
- shellExec(`kubectl delete configmap prometheus-config --ignore-not-found`);
374
- shellExec(`kubectl delete service prometheus --ignore-not-found`);
375
- // Prometheus server host: http://<prometheus-cluster-ip>:9090
376
- const yaml = `${fs.readFileSync(`${underpostRoot}/manifests/prometheus/deployment.yaml`, 'utf8').replace(
377
- '- targets: []',
378
- `- targets: [${options.prom
379
- .split(',')
380
- .map((host) => `'${host}'`)
381
- .join(',')}]`,
382
- )}`;
383
- console.log(yaml);
384
- shellExec(`kubectl apply -f - -n ${options.namespace} <<'EOF'
385
- ${yaml}
386
- EOF
387
- `);
369
+ // Grafana and Prometheus are two faces of one stack, so either flag
370
+ // converges the whole of it — including Alertmanager and the Blackbox
371
+ // Exporter, which the alert rules and probes are useless without. The
372
+ // scrape configuration is rendered from the deploy configuration and the
373
+ // event registry by the monitor CLI; `--prom [hosts]` only adds hosts
374
+ // that configuration does not name.
375
+ if (options.grafana || options.prom) {
376
+ await Underpost.monitor.deployObservability({
377
+ namespace: options.namespace,
378
+ dev: options.dev,
379
+ nodeName: options.nodeName,
380
+ hosts: typeof options.prom === 'string' ? options.prom : options.hosts,
381
+ });
388
382
  }
389
383
 
390
384
  if (options.valkey) {
@@ -396,11 +390,11 @@ EOF
396
390
  // The node port (32079) is set directly in the manifest.
397
391
  if (valkeyReady && options.nodePort)
398
392
  shellExec(`kubectl apply -f ${underpostRoot}/manifests/valkey/valkey-nodeport.yaml -n ${options.namespace}`);
399
- if (valkeyReady && options.nodeSelector)
393
+ if (valkeyReady && options.nodeName)
400
394
  Underpost.cluster.pinToNode({
401
395
  name: 'valkey-service',
402
396
  namespace: options.namespace,
403
- node: options.nodeSelector,
397
+ node: options.nodeName,
404
398
  });
405
399
  if (valkeyReady && serviceHost)
406
400
  Underpost.cluster.syncServiceConnectionEnv({
@@ -417,32 +411,32 @@ EOF
417
411
  // Encrypted store first; when no manifest exists the secret is seeded from its origin
418
412
  // seed path below. A manifest that exists but fails validation raises rather than
419
413
  // silently seeding stale credentials.
420
- if (!Underpost.secret.sops.applyIfPresent('mariadb-secret', options.namespace))
421
- shellExec(
422
- `sudo kubectl create secret generic mariadb-secret --from-file=username=/home/dd/engine/engine-private/mariadb-username --from-file=password=/home/dd/engine/engine-private/mariadb-password --dry-run=client -o yaml | kubectl apply -f - -n ${options.namespace}`,
423
- );
414
+ if (!Underpost.secret.applyIfPresent('mariadb-secret', options.namespace))
415
+ Underpost.secret.applyFromOriginSeed('mariadb-secret', options.namespace);
424
416
  shellExec(`kubectl delete statefulset mariadb-statefulset -n ${options.namespace} --ignore-not-found`);
425
417
 
426
418
  if (options.pullImage) Underpost.cluster.pullImage('mariadb:latest', options);
419
+ // The StatefulSet's volumeClaimTemplate is dynamically provisioned, so the data lands in
420
+ // a subdirectory of the local-path root and inherits that root's label.
421
+ Underpost.cluster.ensureContainerStorageContexts({ extraPaths: ['/data/mariadb'] });
427
422
  shellExec(`kubectl apply -f ${underpostRoot}/manifests/mariadb/storage-class.yaml -n ${options.namespace}`);
428
423
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/mariadb -n ${options.namespace}`);
429
424
  }
430
425
  if (options.mysql) {
431
- if (!Underpost.secret.sops.applyIfPresent('mysql-secret', options.namespace))
432
- shellExec(
433
- `sudo kubectl create secret generic mysql-secret --from-file=username=/home/dd/engine/engine-private/mysql-username --from-file=password=/home/dd/engine/engine-private/mysql-password --dry-run=client -o yaml | kubectl apply -f - -n ${options.namespace}`,
434
- );
435
- shellExec(`sudo mkdir -p /mnt/data`);
436
- shellExec(`sudo chmod 777 /mnt/data`);
437
- shellExec(`sudo chown -R $(whoami):$(whoami) /mnt/data`);
426
+ if (!Underpost.secret.applyIfPresent('mysql-secret', options.namespace))
427
+ Underpost.secret.applyFromOriginSeed('mysql-secret', options.namespace);
428
+ // The data directory is prepared, not opened up: a world-writable host path plus the
429
+ // operator's ownership was standing in for the SELinux label the container actually
430
+ // needed. `container_file_t` is what lets mysqld write here; 0755 root-owned is enough,
431
+ // because the image's entrypoint chowns the tree to its own uid on first start.
432
+ Underpost.cluster.ensureContainerStorageContexts({ extraPaths: ['/data/mysql'] });
438
433
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/mysql -n ${options.namespace}`);
439
434
  }
440
435
  if (options.postgresql) {
441
436
  if (options.pullImage) Underpost.cluster.pullImage('postgres:latest', options);
442
- if (!Underpost.secret.sops.applyIfPresent('postgres-secret', options.namespace))
443
- shellExec(
444
- `sudo kubectl create secret generic postgres-secret --from-file=password=/home/dd/engine/engine-private/postgresql-password --dry-run=client -o yaml | kubectl apply -f - -n ${options.namespace}`,
445
- );
437
+ if (!Underpost.secret.applyIfPresent('postgres-secret', options.namespace))
438
+ Underpost.secret.applyFromOriginSeed('postgres-secret', options.namespace);
439
+ Underpost.cluster.ensureContainerStorageContexts({ extraPaths: ['/data/postgresql'] });
446
440
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/postgresql -n ${options.namespace}`);
447
441
  }
448
442
  if (options.mongodb4) {
@@ -486,11 +480,11 @@ EOF
486
480
  shellExec(
487
481
  `kubectl apply -f ${underpostRoot}/manifests/mongodb-4.4/mongodb-nodeport.yaml -n ${options.namespace}`,
488
482
  );
489
- if (options.nodeSelector)
483
+ if (options.nodeName)
490
484
  Underpost.cluster.pinToNode({
491
485
  name: statefulSetName,
492
486
  namespace: options.namespace,
493
- node: options.nodeSelector,
487
+ node: options.nodeName,
494
488
  });
495
489
  if (serviceHost)
496
490
  Underpost.cluster.syncServiceConnectionEnv({
@@ -518,6 +512,10 @@ EOF
518
512
  });
519
513
  }
520
514
 
515
+ // After both StatefulSet branches, so one invocation can bring up MongoDB and its inspector
516
+ // and the client reads the auth mode from the set this run just applied.
517
+ if (options.mongoExpress) await MongoExpress.deploy({ namespace: options.namespace, underpostRoot, options });
518
+
521
519
  // Installing one stack must never break the other. Whichever is already
522
520
  // present decides whether this install takes the node's 80/443 for itself
523
521
  // or joins the underpost ingress, so it is read before anything is applied.
@@ -724,13 +722,107 @@ EOF
724
722
  return { type, ready, nodes };
725
723
  },
726
724
 
725
+ /**
726
+ * @method discoverLocalPathRoots
727
+ * @description Reads the node directories the local-path provisioner writes into, from its
728
+ * live ConfigMap. Every dynamically provisioned claim in this platform (Grafana, Prometheus,
729
+ * Alertmanager, IPFS, MariaDB) becomes a subdirectory of one of them, so the root has to be
730
+ * discovered rather than assumed — a wrong guess leaves those claims carrying the `/opt`
731
+ * policy default (`usr_t`), which no `container_t` pod can write.
732
+ * @returns {string[]} Configured node paths; empty when no provisioner is reachable.
733
+ * @memberof UnderpostCluster
734
+ */
735
+ discoverLocalPathRoots() {
736
+ for (const namespace of ContainerStorageService.LOCAL_PATH_NAMESPACES) {
737
+ const config = `${
738
+ shellExec(localPathConfigCommandFactory({ namespace }), {
739
+ stdout: true,
740
+ silent: true,
741
+ silentOnError: true,
742
+ disableLog: true,
743
+ }) || ''
744
+ }`.trim();
745
+ const roots = localPathRootsFactory(config);
746
+ if (roots.length > 0) return roots;
747
+ }
748
+ return [];
749
+ },
750
+
751
+ /**
752
+ * @method ensureContainerStorageContexts
753
+ * @description Makes SELinux compatibility an invariant of the storage lifecycle rather than
754
+ * a one-time bring-up step: creates the node directories this platform hands to containers
755
+ * (only when missing, so live data trees keep their ownership and mode), registers the
756
+ * persistent `container_file_t` mapping for each, and restores the trees.
757
+ *
758
+ * Idempotent and safe to call on every deploy. Never relabels paths outside the discovered
759
+ * set, and never changes SELinux mode.
760
+ * @param {object} [options]
761
+ * @param {boolean} [options.controlPlane=false] - Also cover the kubeadm control-plane trees
762
+ * bind-mounted into containers (`/etc/kubernetes`, `/var/lib/etcd`, `/var/lib/calico`).
763
+ * @param {string[]} [options.extraPaths=[]] - Additional node directories to include.
764
+ * @returns {string[]} The roots that were prepared.
765
+ * @memberof UnderpostCluster
766
+ */
767
+ ensureContainerStorageContexts(options = {}) {
768
+ const roots = containerStorageRootsFactory({
769
+ localPathRoots: Underpost.cluster.discoverLocalPathRoots(),
770
+ extraPaths: options.extraPaths || [],
771
+ controlPlane: options.controlPlane === true,
772
+ });
773
+ logger.info('Preparing container-mounted host storage', { roots });
774
+ // HOST_VOLUME_ROOT is the one root the deploy flow writes into unprivileged (it lives in the
775
+ // operator's home tree and receives each hostPath volume's contents), so it is created owned
776
+ // by the invoking user. The rest stay root-owned: their subdirectories are chowned by each
777
+ // workload's own init container, which is the single owner of that concern.
778
+ const { uid, gid } = os.userInfo();
779
+ const operatorRoots = roots.filter((root) => root === HOST_VOLUME_ROOT);
780
+ const systemRoots = roots.filter((root) => root !== HOST_VOLUME_ROOT);
781
+ if (systemRoots.length > 0) ensureContainerStorage(systemRoots, { execute: shellExec });
782
+ if (operatorRoots.length > 0)
783
+ ensureContainerStorage(operatorRoots, { execute: shellExec, owner: `${uid}:${gid}` });
784
+ return roots;
785
+ },
786
+
787
+ /**
788
+ * @method ensureLocalPathProvisioner
789
+ * @description Ensures dynamic local-path PVC provisioning is available.
790
+ * @returns {string} Namespace containing the ready provisioner.
791
+ * @memberof UnderpostCluster
792
+ */
793
+ ensureLocalPathProvisioner() {
794
+ const locations = ['local-path-storage', 'kube-system'];
795
+ let namespace = locations.find((candidate) =>
796
+ `${
797
+ shellExec(`kubectl get deployment local-path-provisioner -n ${candidate} -o name`, {
798
+ stdout: true,
799
+ silent: true,
800
+ silentOnError: true,
801
+ disableLog: true,
802
+ }) || ''
803
+ }`.trim(),
804
+ );
805
+
806
+ if (!namespace) {
807
+ logger.info('Installing local-path-provisioner');
808
+ shellExec(`kubectl apply -f ${LOCAL_PATH_PROVISIONER_MANIFEST}`);
809
+ namespace = 'local-path-storage';
810
+ }
811
+ shellExec(`kubectl rollout status deployment/local-path-provisioner -n ${namespace} --timeout=5m`);
812
+ // The provisioner's root exists (or is about to) only now, and its helper pod creates each
813
+ // claim directory by inheriting that root's label. Prepare it here so the first dynamically
814
+ // provisioned claim already lands on `container_file_t` instead of `/opt`'s `usr_t`.
815
+ Underpost.cluster.ensureContainerStorageContexts();
816
+ return namespace;
817
+ },
818
+
727
819
  /**
728
820
  * @method pinToNode
729
821
  * @description Pins a workload to a specific Kubernetes node by patching its
730
822
  * pod template with a `kubernetes.io/hostname` nodeSelector. General-purpose;
731
- * currently used to place the MongoDB 4.4 / Valkey StatefulSets on a chosen
732
- * node (`--node-selector`). The patch triggers a rolling reschedule onto the
733
- * target node.
823
+ * currently used to place the MongoDB 4.4 / Valkey StatefulSets and the
824
+ * observability Deployments on a chosen node (`--node-name`). The patch
825
+ * triggers a rolling reschedule onto the target node.
734
826
  * @param {object} params
735
827
  * @param {string} [params.kind='statefulset'] - Workload kind to patch.
736
828
  * @param {string} params.name - Workload name.
@@ -1383,6 +1475,16 @@ EOF
1383
1475
  config(options = { underpostRoot: '.' }) {
1384
1476
  const { underpostRoot } = options;
1385
1477
  console.log('Applying host configuration: SELinux, Docker, Containerd, and Sysctl settings.');
1478
+ // Label before enforcing, never after: flipping the mode first would put the host into
1479
+ // Enforcing with the storage trees still carrying the policy default, and every pod that
1480
+ // mounts one would start failing for real instead of only logging a denial.
1481
+ //
1482
+ // Registered on every run, not only at first cluster creation: the node directories backing
1483
+ // PersistentVolumes are recreated by resets, by `DirectoryOrCreate`, and by the local-path
1484
+ // helper pod long after `kubeadm init` ran, and each of those inherits the policy default
1485
+ // unless the mapping is already in the store.
1486
+ ensureSELinuxTooling();
1487
+ Underpost.cluster.ensureContainerStorageContexts();
1386
1488
  enforceSELinux(['/var/lib/kubelet', '/var/lib/containerd']);
1387
1489
 
1388
1490
  // Enable and start Docker and Kubelet services
@@ -1439,8 +1541,11 @@ EOF
1439
1541
  // forever (the upstream unit ships TimeoutStartSec=0).
1440
1542
  shellExec(`if systemctl is-active --quiet firewalld; then sudo systemctl disable --now firewalld; fi`);
1441
1543
 
1544
+ // Storage labeling precedes the Enforcing flip, so the mode is never activated over trees
1545
+ // that still carry the policy default.
1546
+ ensureSELinuxTooling();
1547
+ Underpost.cluster.ensureContainerStorageContexts();
1442
1548
  enforceSELinux(K3S_SELINUX_PATHS);
1443
- shareWithContainers(HOST_VOLUME_PATHS);
1444
1549
 
1445
1550
  // Disable swap. `swapoff -a` is a no-op without swap; the sed only edits
1446
1551
  // fstab when a swap line is present.
@@ -1714,6 +1819,10 @@ fi`);
1714
1819
  else logger.info(' -> Skipping (pass --remove-volume-host-paths to enable).');
1715
1820
 
1716
1821
  logger.info('Phase 2/7: Enforcing SELinux and restoring runtime contexts...');
1822
+ // The hostPath cleanup above emptied the volume trees; re-asserting the mapping here means
1823
+ // a rebuild starts from correctly labeled storage instead of inheriting the policy default.
1824
+ ensureSELinuxTooling();
1825
+ Underpost.cluster.ensureContainerStorageContexts();
1717
1826
  enforceSELinux(['/var/lib/kubelet', '/var/lib/containerd']);
1718
1827
 
1719
1828
  logger.info('Phase 3/7: Stopping host kubelet and container runtimes (kubeadm-scope only)...');
@@ -1916,7 +2025,7 @@ EOF`);
1916
2025
 
1917
2026
  // SOPS and Age for Git-native encrypted secret manifests. Owned by UnderpostSecret so the
1918
2027
  // same idempotent install backs `underpost secret --install-tools`.
1919
- Underpost.secret.sops.installTooling();
2028
+ Underpost.secret.installTooling();
1920
2029
 
1921
2030
  // Install snap
1922
2031
  shellExec(`sudo yum install -y snapd`);