@underpostnet/cyberia 3.3.0 → 3.3.73

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 (471) hide show
  1. package/.dockerignore +1 -0
  2. package/.github/workflows/coverall.cyberia.ci.yml +34 -14
  3. package/.github/workflows/cyberia-client.cd.yml +5 -0
  4. package/.github/workflows/cyberia-server.cd.yml +5 -0
  5. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  6. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  7. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  8. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  9. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  10. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  11. package/.github/workflows/engine-cyberia.cd.yml +3 -0
  12. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  13. package/.github/workflows/ghpkg.ci.yml +35 -20
  14. package/.github/workflows/hardhat.ci.yml +12 -11
  15. package/.github/workflows/npmpkg.ci.yml +17 -15
  16. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  17. package/.github/workflows/release.cd.yml +1 -0
  18. package/.prettierignore +1 -0
  19. package/AGENTS.md +47 -0
  20. package/CHANGELOG.md +565 -2510
  21. package/CLI-HELP.md +306 -147
  22. package/Dockerfile +25 -9
  23. package/Dockerfile.dev +25 -9
  24. package/Dockerfile.test +4 -4
  25. package/README.md +21 -1
  26. package/bin/build.js +66 -41
  27. package/bin/build.template.js +8 -3
  28. package/bin/cyberia.js +308 -91
  29. package/bin/deploy.js +18 -104
  30. package/bin/index.js +308 -91
  31. package/conf.js +91 -4
  32. package/deploy/cyberia-client/deploy.sh +47 -0
  33. package/deploy/cyberia-client/package.sh +18 -0
  34. package/deploy/cyberia-client/state.sh +14 -0
  35. package/deploy/cyberia-server/deploy.sh +47 -0
  36. package/deploy/cyberia-server/package.sh +18 -0
  37. package/deploy/cyberia-server/state.sh +14 -0
  38. package/deploy/dd-cyberia/deploy.sh +6 -26
  39. package/deploy/dd-cyberia/init.sh +35 -43
  40. package/deploy/dd-cyberia/package.sh +17 -0
  41. package/deploy/dd-cyberia/state.sh +14 -0
  42. package/deploy/dd-cyberia/sync-deploy.sh +92 -170
  43. package/deploy/lib/github-actions-logging.sh +594 -0
  44. package/deploy/lib/host.sh +185 -0
  45. package/deploy/lib/state.sh +62 -0
  46. package/deploy/pwa-microservices-template/deploy.sh +12 -39
  47. package/deploy/release/deploy.sh +9 -39
  48. package/deployment.yaml +7 -2
  49. package/docker-compose.yml +7 -7
  50. package/examples/static-page/README.md +19 -19
  51. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  52. package/hardhat/hardhat.config.js +1 -6
  53. package/hardhat/package-lock.json +101 -40
  54. package/hardhat/package.json +2 -2
  55. package/manifests/alertmanager/deployment.yaml +81 -0
  56. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  57. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
  58. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
  59. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  60. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  61. package/manifests/grafana/deployment.yaml +26 -7
  62. package/manifests/grafana/kustomization.yaml +1 -0
  63. package/manifests/grafana/service.yaml +6 -1
  64. package/manifests/mariadb/pv.yaml +1 -0
  65. package/manifests/mongodb/statefulset.yaml +9 -2
  66. package/manifests/mysql/pv-pvc.yaml +14 -1
  67. package/manifests/postgresql/pv.yaml +12 -1
  68. package/manifests/postgresql/pvc.yaml +1 -0
  69. package/manifests/prometheus/deployment.yaml +18 -22
  70. package/package.json +83 -10
  71. package/scripts/event-monitor.sh +56 -0
  72. package/scripts/k3s-node-setup.sh +27 -14
  73. package/scripts/kubeadm-node-setup.sh +31 -11
  74. package/scripts/maas-setup.sh +8 -8
  75. package/scripts/selinux-normalize.sh +907 -0
  76. package/scripts/shutdown-machine.sh +843 -0
  77. package/scripts/test-monitor.sh +3 -3
  78. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
  79. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
  80. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
  81. package/src/api/core/core.controller.js +1 -1
  82. package/src/api/core/core.router.js +2 -2
  83. package/src/api/core/core.service.js +2 -2
  84. package/src/api/crypto/crypto.controller.js +1 -1
  85. package/src/api/crypto/crypto.service.js +1 -1
  86. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  87. package/src/api/cyberia-action/cyberia-action.router.js +1 -1
  88. package/src/api/cyberia-action/cyberia-action.service.js +2 -2
  89. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
  90. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
  91. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
  92. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  93. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
  94. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  95. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  96. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  97. package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
  98. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
  99. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
  100. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
  101. package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
  102. package/src/api/cyberia-instance/cyberia-fallback-world.js +8 -0
  103. package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
  104. package/src/api/cyberia-instance/cyberia-instance.controller.js +1 -1
  105. package/src/api/cyberia-instance/cyberia-instance.router.js +2 -2
  106. package/src/api/cyberia-instance/cyberia-instance.service.js +2 -2
  107. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  108. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  109. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
  110. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  111. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  112. package/src/api/cyberia-map/cyberia-map.service.js +2 -2
  113. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  114. package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
  115. package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
  116. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  117. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  118. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  119. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  120. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  121. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  122. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +0 -26
  123. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  124. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  125. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  126. package/src/api/default/default.controller.js +1 -1
  127. package/src/api/default/default.router.js +1 -1
  128. package/src/api/default/default.service.js +2 -2
  129. package/src/api/document/document.controller.js +1 -1
  130. package/src/api/document/document.router.js +1 -1
  131. package/src/api/document/document.service.js +2 -2
  132. package/src/api/file/file.controller.js +1 -1
  133. package/src/api/file/file.router.js +1 -1
  134. package/src/api/file/file.service.js +2 -2
  135. package/src/api/instance/instance.controller.js +1 -1
  136. package/src/api/instance/instance.router.js +1 -1
  137. package/src/api/instance/instance.service.js +2 -2
  138. package/src/api/ipfs/ipfs.controller.js +1 -1
  139. package/src/api/ipfs/ipfs.router.js +2 -2
  140. package/src/api/ipfs/ipfs.service.js +2 -2
  141. package/src/api/object-layer/object-layer.controller.js +1 -1
  142. package/src/api/object-layer/object-layer.router.js +2 -2
  143. package/src/api/object-layer/object-layer.service.js +3 -3
  144. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  145. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  146. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  147. package/src/api/test/test.controller.js +1 -1
  148. package/src/api/test/test.service.js +1 -1
  149. package/src/api/user/guest.service.js +3 -3
  150. package/src/api/user/user.controller.js +1 -1
  151. package/src/api/user/user.router.js +2 -2
  152. package/src/api/user/user.service.js +4 -4
  153. package/src/api.js +5 -9
  154. package/src/cli/app.js +391 -0
  155. package/src/cli/baremetal.js +30 -35
  156. package/src/cli/client.js +306 -0
  157. package/src/cli/cloud-init.js +3 -3
  158. package/src/cli/cluster.js +184 -82
  159. package/src/cli/db.js +120 -68
  160. package/src/cli/deploy.js +153 -71
  161. package/src/cli/docker-compose.js +5 -5
  162. package/src/cli/domains.js +184 -0
  163. package/src/cli/dotenv-store.js +143 -0
  164. package/src/cli/event.js +2281 -0
  165. package/src/cli/fs.js +3 -3
  166. package/src/cli/host.js +672 -0
  167. package/src/cli/image.js +4 -6
  168. package/src/cli/index.js +322 -142
  169. package/src/cli/ipfs.js +34 -30
  170. package/src/cli/kickstart.js +1 -1
  171. package/src/cli/kubectl.js +218 -41
  172. package/src/cli/lxd.js +3 -3
  173. package/src/cli/monitor.js +1359 -26
  174. package/src/cli/package.js +90 -0
  175. package/src/cli/release.js +16 -12
  176. package/src/cli/repository.js +558 -363
  177. package/src/cli/run.js +331 -650
  178. package/src/cli/secrets.js +2158 -964
  179. package/src/cli/ssh.js +478 -279
  180. package/src/cli/state.js +394 -0
  181. package/src/cli/static.js +2 -2
  182. package/src/cli/system.js +1 -1
  183. package/src/cli/test.js +199 -125
  184. package/src/cli/vultr.js +61 -21
  185. package/src/cli/wireguard.js +1111 -306
  186. package/src/client/components/core/CalendarCore.js +53 -96
  187. package/src/client/components/core/Docs.js +258 -211
  188. package/src/client/components/core/FileExplorer.js +0 -21
  189. package/src/client/components/core/PanelForm.js +4 -4
  190. package/src/client/components/core/Repository.js +56 -0
  191. package/src/client/components/core/Translate.js +7 -0
  192. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  193. package/src/client/components/core/Wallet.js +0 -11
  194. package/src/client/components/core/Worker.js +7 -1
  195. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  196. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -1
  197. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  198. package/src/client/components/default/AppShellDefault.js +1 -1
  199. package/src/client/components/default/SettingsDefault.js +2 -2
  200. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  201. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  202. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  203. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
  204. package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
  205. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  206. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  207. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  208. package/src/client/public/default/android-chrome-144x144.png +0 -0
  209. package/src/client/public/default/android-chrome-192x192.png +0 -0
  210. package/src/client/public/default/android-chrome-256x256.png +0 -0
  211. package/src/client/public/default/android-chrome-36x36.png +0 -0
  212. package/src/client/public/default/android-chrome-384x384.png +0 -0
  213. package/src/client/public/default/android-chrome-48x48.png +0 -0
  214. package/src/client/public/default/android-chrome-512x512.png +0 -0
  215. package/src/client/public/default/android-chrome-72x72.png +0 -0
  216. package/src/client/public/default/android-chrome-96x96.png +0 -0
  217. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  218. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  219. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  220. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  221. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  222. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  223. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  224. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  225. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  226. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  227. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  228. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  229. package/src/client/public/default/apple-touch-icon.png +0 -0
  230. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  231. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  232. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  233. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  234. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  235. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  236. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  237. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  238. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  239. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  240. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  241. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  242. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  243. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  244. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  245. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  246. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  247. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  248. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  249. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  250. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  251. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  252. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  253. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  254. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  255. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  256. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  257. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  258. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  259. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  260. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  261. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  262. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  263. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  264. package/src/client/public/default/assets/background/white.jpg +0 -0
  265. package/src/client/public/default/browserconfig.xml +1 -1
  266. package/src/client/public/default/favicon-16x16.png +0 -0
  267. package/src/client/public/default/favicon-32x32.png +0 -0
  268. package/src/client/public/default/favicon-48x48.png +0 -0
  269. package/src/client/public/default/favicon.ico +0 -0
  270. package/src/client/public/default/manifest.webmanifest +5 -5
  271. package/src/client/public/default/mstile-144x144.png +0 -0
  272. package/src/client/public/default/mstile-150x150.png +0 -0
  273. package/src/client/public/default/mstile-310x150.png +0 -0
  274. package/src/client/public/default/mstile-310x310.png +0 -0
  275. package/src/client/public/default/mstile-70x70.png +0 -0
  276. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  277. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  278. package/src/client/ssr/RootDocument.js +1 -1
  279. package/src/client/ssr/body/404.js +1 -1
  280. package/src/client/ssr/body/500.js +1 -1
  281. package/src/client/ssr/body/CacheControl.js +1 -1
  282. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  283. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  284. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  285. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  286. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  287. package/src/client/ssr/head/Css.js +1 -1
  288. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  289. package/src/client/ssr/head/DefaultScripts.js +1 -1
  290. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  291. package/src/client/ssr/head/Microdata.js +1 -1
  292. package/src/client/ssr/head/Production.js +1 -1
  293. package/src/client/ssr/head/Pwa.js +1 -1
  294. package/src/client/ssr/head/PwaItemledger.js +1 -1
  295. package/src/client/ssr/head/Seo.js +1 -1
  296. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  297. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  298. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  299. package/src/client/ssr/views/Cyberia404.js +7 -5
  300. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  301. package/src/client/ssr/views/Maintenance.js +1 -1
  302. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  303. package/src/client/ssr/views/Test.js +1 -1
  304. package/src/client/sw/core.sw.js +20 -14
  305. package/src/client-builder/client-build-docs.js +61 -46
  306. package/src/client-builder/client-build-live.js +2 -2
  307. package/src/client-builder/client-build.js +38 -30
  308. package/src/client-builder/client-dev-server.js +3 -3
  309. package/src/client-builder/client-icons.js +2 -2
  310. package/src/client-builder/ssr.js +3 -3
  311. package/src/client.build.js +3 -6
  312. package/src/client.dev.js +3 -6
  313. package/src/db/DataBaseProvider.js +186 -3
  314. package/src/db/mariadb/MariaDB.js +3 -2
  315. package/src/db/mongo/MongoBootstrap.js +273 -101
  316. package/src/db/mongo/MongooseDB.js +7 -8
  317. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  318. package/src/grpc/cyberia/grpc-server.js +1 -1
  319. package/src/index.js +79 -23
  320. package/src/mailer/EmailRender.js +2 -2
  321. package/src/mailer/MailerInterceptor.js +87 -0
  322. package/src/mailer/MailerProvider.js +50 -6
  323. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
  324. package/src/projects/cyberia/besu-genesis-generator.js +3 -3
  325. package/src/projects/cyberia/catalog-cyberia.js +53 -10
  326. package/src/projects/cyberia/gemini-client.js +1 -1
  327. package/src/projects/cyberia/generate-saga.js +1 -1
  328. package/src/projects/cyberia/hot-reload-trigger.js +1 -1
  329. package/src/projects/cyberia/instance-data.js +1 -1
  330. package/src/projects/cyberia/ipfs-client.js +4 -4
  331. package/src/projects/cyberia/map-preview-generator.js +1 -1
  332. package/src/projects/cyberia/object-layer.js +1 -1
  333. package/src/projects/cyberia/semantic-layer-generator.js +1 -1
  334. package/src/projects/underpost/catalog-underpost.js +9 -1
  335. package/src/proxy.js +4 -7
  336. package/src/runtime/cyberia-client/Dockerfile +9 -4
  337. package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
  338. package/src/runtime/cyberia-server/Dockerfile +9 -4
  339. package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
  340. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  341. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  342. package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
  343. package/src/runtime/engine-cyberia/docker-compose.yml +7 -7
  344. package/src/runtime/express/Express.js +32 -27
  345. package/src/runtime/lampp/Lampp.js +22 -70
  346. package/src/runtime/nginx/Nginx.js +1 -1
  347. package/src/runtime/wp/Wp.js +16 -48
  348. package/src/server/{catalog.js → build/catalog.js} +15 -5
  349. package/src/server/build/coverage.js +117 -0
  350. package/src/server/build/execution.js +402 -0
  351. package/src/server/build/package.js +465 -0
  352. package/src/server/build/testing.js +528 -0
  353. package/src/server/{dns.js → network/dns.js} +144 -11
  354. package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
  355. package/src/server/{middlewares.js → network/middlewares.js} +3 -3
  356. package/src/server/network/node-capability.js +98 -0
  357. package/src/server/{peer.js → network/peer.js} +3 -3
  358. package/src/server/{proxy.js → network/proxy.js} +7 -13
  359. package/src/server/network/router.js +356 -0
  360. package/src/server/{tls.js → network/tls.js} +2 -2
  361. package/src/server/{underpost-compression.js → network/underpost-compression.js} +1 -1
  362. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
  363. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
  364. package/src/server/{cri.js → ops/cri.js} +2 -2
  365. package/src/server/{cron.js → ops/cron.js} +349 -74
  366. package/src/server/ops/event-notification.js +284 -0
  367. package/src/server/{logger.js → ops/logger.js} +108 -23
  368. package/src/server/ops/monitoring.js +1724 -0
  369. package/src/server/{systemd.js → ops/systemd.js} +55 -1
  370. package/src/server/{conf.js → runtime/conf.js} +513 -422
  371. package/src/server/runtime/config-scope.js +215 -0
  372. package/src/server/runtime/environment.js +149 -0
  373. package/src/server/{process.js → runtime/process.js} +153 -12
  374. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  375. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  376. package/src/server/{start.js → runtime/start.js} +128 -39
  377. package/src/server/{auth.js → security/auth.js} +7 -8
  378. package/src/server/security/container-storage.js +382 -0
  379. package/src/server/{crypto.js → security/crypto.js} +1 -1
  380. package/src/server/{selinux.js → security/selinux.js} +1 -1
  381. package/src/server/{backup.js → storage/backup.js} +17 -8
  382. package/src/server/{data-query.js → storage/data-query.js} +1 -1
  383. package/src/server/{downloader.js → storage/downloader.js} +2 -2
  384. package/src/server/storage/repository.js +68 -0
  385. package/src/server.js +4 -7
  386. package/src/ws/IoInterface.js +1 -1
  387. package/src/ws/IoServer.js +1 -1
  388. package/src/ws/core/core.ws.connection.js +1 -1
  389. package/src/ws/core/core.ws.emit.js +1 -1
  390. package/src/ws/core/core.ws.server.js +1 -1
  391. package/src/ws/default/default.ws.connection.js +1 -1
  392. package/src/ws/default/default.ws.emit.js +1 -1
  393. package/src/ws/default/default.ws.server.js +1 -1
  394. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  395. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  396. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  397. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  398. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
  399. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +1 -1
  400. package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
  401. package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
  402. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  403. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  404. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  405. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  406. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  407. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  408. package/test/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
  409. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  410. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  411. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  412. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  413. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  414. package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
  415. package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +609 -55
  416. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  417. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  418. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  419. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  420. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  421. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  422. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +6 -6
  423. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -4
  424. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  425. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  426. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  427. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  428. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  429. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  430. package/test/support/shell-harness.js +73 -0
  431. package/test/unit/build-template.test.js +97 -0
  432. package/test/unit/build-workflow-offline.test.js +132 -0
  433. package/test/unit/catalog.test.js +71 -0
  434. package/test/unit/client-build-docs.test.js +334 -0
  435. package/test/unit/conf-loading.test.js +303 -0
  436. package/test/unit/conf-resolution.test.js +979 -0
  437. package/test/unit/coverage-artifact.test.js +130 -0
  438. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  439. package/test/unit/deploy-env-resolution.test.js +38 -0
  440. package/test/unit/deploy-log-table.test.js +447 -0
  441. package/test/unit/execution-profiles.test.js +219 -0
  442. package/test/unit/fleet-sync-source.test.js +149 -0
  443. package/test/unit/logger-redaction.test.js +112 -0
  444. package/test/unit/package.test.js +403 -0
  445. package/test/unit/prepare-host.test.js +299 -0
  446. package/test/unit/process-environment.test.js +18 -0
  447. package/test/unit/propagation-message.test.js +78 -0
  448. package/test/unit/redeploy-plan.test.js +24 -0
  449. package/test/unit/release-bump.test.js +474 -0
  450. package/test/unit/ssh-output-redaction.test.js +28 -0
  451. package/test/unit/start-options.test.js +46 -0
  452. package/test/unit/test-tiers.test.js +193 -0
  453. package/vitest.config.js +58 -0
  454. package/.nycrc +0 -9
  455. package/deploy/lib/logging.sh +0 -96
  456. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  457. package/manifests/mongodb/pv-pvc.yaml +0 -59
  458. package/scripts/coverall-test-cyberia.sh +0 -24
  459. package/scripts/coverall-test.sh +0 -24
  460. package/scripts/link-local-underpost-cli.sh +0 -6
  461. package/src/api/user/user.build.js +0 -16
  462. package/src/cli/env.js +0 -177
  463. package/src/client/components/core/Blockchain.js +0 -41
  464. package/src/client/components/core/Blog.js +0 -9
  465. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  466. package/src/client/public/default/assets/background/dark.jpg +0 -0
  467. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  468. package/src/client/public/default/assets/background/white0.jpg +0 -0
  469. package/src/client/public/doc/favicon.ico +0 -0
  470. package/src/client/public/doc/sitemap +0 -148
  471. package/src/server/environment.js +0 -98
@@ -0,0 +1,382 @@
1
+ /**
2
+ * Host filesystem preparation for Kubernetes storage that unprivileged containers mount.
3
+ *
4
+ * Every node-local path a pod reaches through a `hostPath` PersistentVolume — or through a
5
+ * dynamic provisioner that is itself backed by a node directory — must carry a type the
6
+ * `container_t` domain can use. The base RHEL/Rocky policy has no mapping for the trees this
7
+ * platform writes into, so a directory created there falls back to the policy default
8
+ * (`default_t` under `/data`, `usr_t` under `/opt`, `user_home_t` under the operator's home) and
9
+ * every read and write from a pod becomes an AVC denial.
10
+ *
11
+ * The mapping is registered with `semanage fcontext` rather than applied with `chcon` so it
12
+ * survives a relabel, a policy update and `/.autorelabel`; the paths are then restored. Both
13
+ * operations are idempotent, which is what lets deploy, redeploy and recovery flows all call
14
+ * this without special-casing.
15
+ *
16
+ * @module src/server/security/container-storage.js
17
+ * @namespace ContainerStorageService
18
+ */
19
+ 'use strict';
20
+
21
+ import SELinuxService, { runSELinuxCommands, shellArgumentFactory } from './selinux.js';
22
+ import { HOST_VOLUME_ROOT } from '../runtime/environment.js';
23
+
24
+ /**
25
+ * Host storage preparation and SELinux labeling for container-mounted paths.
26
+ * @class ContainerStorageService
27
+ * @memberof ContainerStorageService
28
+ */
29
+ class ContainerStorageService {
30
+ /** Label every unprivileged container domain can read and write, at the empty category set. */
31
+ static SHARED_CONTAINER_TYPE = SELinuxService.SHARED_CONTAINER_TYPE;
32
+
33
+ /**
34
+ * Mode used when this module is the one creating the directory. Existing directories keep the
35
+ * mode, ownership and ACLs they already have — the workload's own init container owns that,
36
+ * and resetting it would rewrite live data trees.
37
+ */
38
+ static DEFAULT_MODE = '0755';
39
+
40
+ /** Upstream rancher local-path-provisioner defaults, used only when discovery finds nothing. */
41
+ static LOCAL_PATH_DEFAULT_ROOT = '/opt/local-path-provisioner';
42
+ static LOCAL_PATH_CONFIG_MAP = 'local-path-config';
43
+ static LOCAL_PATH_NAMESPACES = ['local-path-storage', 'kube-system'];
44
+
45
+ /**
46
+ * Node directories this platform owns and hands to containers. `/data` covers the MongoDB
47
+ * replica volumes, MariaDB, MySQL and PostgreSQL trees; `HOST_VOLUME_ROOT` covers every
48
+ * `hostPath` PersistentVolume the deploy flow materializes, including the gateway's static tree.
49
+ */
50
+ static PLATFORM_STORAGE_ROOTS = ['/data', HOST_VOLUME_ROOT];
51
+
52
+ /**
53
+ * Kubernetes control-plane state bind-mounted into containers by kubeadm.
54
+ */
55
+ static CONTROL_PLANE_MOUNT_PATHS = ['/etc/kubernetes', '/var/lib/etcd', '/var/lib/calico'];
56
+
57
+ /**
58
+ * Directories that are a system location in their own right. A storage tree may live *under*
59
+ * one of these (`/opt/local-path-provisioner`, `/var/lib/etcd`), but the directory itself never
60
+ * becomes container storage.
61
+ */
62
+ static PROTECTED_EXACT_PATHS = [
63
+ '/',
64
+ '/boot',
65
+ '/dev',
66
+ '/etc',
67
+ '/home',
68
+ '/mnt',
69
+ '/opt',
70
+ '/proc',
71
+ '/root',
72
+ '/run',
73
+ '/srv',
74
+ '/sys',
75
+ '/tmp',
76
+ '/usr',
77
+ '/var',
78
+ '/var/lib',
79
+ '/var/log',
80
+ '/var/run',
81
+ ];
82
+
83
+ /**
84
+ * Trees no container storage may live in at all.
85
+ *
86
+ * A host directory being mounted into a pod is not evidence that it holds workload data: the
87
+ * CNI plugin directory, the runtime socket and `/proc` are all mounted into pods, and each has
88
+ * a policy type that exists for a reason. Relabeling `/opt/cni/bin` would strip `bin_t` from
89
+ * the calico executables the kubelet runs, which is a worse outcome than the denial it set out
90
+ * to fix.
91
+ */
92
+ static PROTECTED_PATH_PREFIXES = [
93
+ '/bin',
94
+ '/boot',
95
+ '/dev',
96
+ '/etc',
97
+ '/lib',
98
+ '/lib64',
99
+ '/opt/cni',
100
+ '/proc',
101
+ '/run',
102
+ '/sbin',
103
+ '/sys',
104
+ '/usr',
105
+ ];
106
+
107
+ /**
108
+ * The one set of paths allowed to break {@link PROTECTED_PATH_PREFIXES}: kubeadm bind-mounts
109
+ * these into its control-plane containers, so they genuinely are container-visible state. They
110
+ * are a hardcoded constant, never something discovery or an operator flag can widen.
111
+ */
112
+ static PROTECTED_PATH_EXCEPTIONS = ContainerStorageService.CONTROL_PLANE_MOUNT_PATHS;
113
+
114
+ /**
115
+ * Reports whether a path may be given the shared container label.
116
+ * @param {string} path - Absolute path.
117
+ * @returns {boolean}
118
+ */
119
+ static isSafeStoragePath(path) {
120
+ if (typeof path !== 'string' || !path.startsWith('/')) return false;
121
+ const normalized = path.replace(/\/+$/, '') || '/';
122
+ if (ContainerStorageService.PROTECTED_PATH_EXCEPTIONS.includes(normalized)) return true;
123
+ if (ContainerStorageService.PROTECTED_EXACT_PATHS.includes(normalized)) return false;
124
+ return !ContainerStorageService.PROTECTED_PATH_PREFIXES.some(
125
+ (prefix) => normalized === prefix || normalized.startsWith(`${prefix}/`),
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Throws unless every path may be labeled. Applied at the command-building boundary so no
131
+ * caller — a discovery result, a CLI `extraPaths`, a future one — can route around it.
132
+ * @param {string[]} paths - Absolute paths.
133
+ * @returns {string[]} The same paths.
134
+ */
135
+ static assertSafeStoragePaths(paths = []) {
136
+ const refused = paths.filter((path) => !ContainerStorageService.isSafeStoragePath(path));
137
+ if (refused.length > 0)
138
+ throw new RangeError(
139
+ `refusing to apply the container storage label to a system path: ${refused.join(', ')}. ` +
140
+ `A host directory mounted into a pod is not necessarily workload data; give the volume ` +
141
+ `its own directory under a declared storage root instead.`,
142
+ );
143
+ return paths;
144
+ }
145
+
146
+ /**
147
+ * Deduplicates and sorts a path list, keeping only absolute entries.
148
+ * @param {string[]} [paths] - Candidate paths.
149
+ * @returns {string[]} Absolute paths, parents before their descendants.
150
+ */
151
+ static absoluteStoragePaths(paths = []) {
152
+ return [
153
+ ...new Set(
154
+ paths
155
+ .filter((path) => typeof path === 'string')
156
+ .map((path) => path.trim().replace(/\/+$/, ''))
157
+ .filter((path) => path.startsWith('/') && path !== '/'),
158
+ ),
159
+ ].sort();
160
+ }
161
+
162
+ /**
163
+ * Reduces a path list to the smallest set of roots that still covers every entry.
164
+ *
165
+ * A `semanage fcontext` mapping is the regular expression `<root>(/.*)?`, so a root already
166
+ * covers all of its descendants; keeping both `/data` and `/data/mongodb` would add a redundant
167
+ * rule and a second full `restorecon` pass over the same tree on every deploy.
168
+ * @param {string[]} [paths] - Candidate absolute paths.
169
+ * @returns {string[]} Non-overlapping, sorted roots.
170
+ */
171
+ static normalizeStorageRoots(paths = []) {
172
+ const absolute = ContainerStorageService.absoluteStoragePaths(paths);
173
+ return absolute.filter(
174
+ (path) => !absolute.some((candidate) => candidate !== path && path.startsWith(`${candidate}/`)),
175
+ );
176
+ }
177
+
178
+ /**
179
+ * Extracts the node directories a local-path provisioner writes into, from its `config.json`.
180
+ *
181
+ * Read rather than assumed: the provisioner's root is operator-configurable, and every
182
+ * dynamically provisioned claim in this platform (Grafana, Prometheus, Alertmanager, IPFS,
183
+ * MariaDB) becomes a subdirectory of it. Labeling the wrong root leaves those claims with the
184
+ * `/opt` policy default (`usr_t`), which is exactly the shape of the Grafana denials.
185
+ * @param {string} [configJson] - Contents of the provisioner ConfigMap's `config.json` key.
186
+ * @returns {string[]} Configured node paths; empty when the config is absent or unparsable.
187
+ */
188
+ static localPathRootsFactory(configJson = '') {
189
+ if (!configJson || !`${configJson}`.trim()) return [];
190
+ let config;
191
+ try {
192
+ config = JSON.parse(configJson);
193
+ } catch {
194
+ return [];
195
+ }
196
+ const paths = [];
197
+ if (Array.isArray(config?.nodePathMap))
198
+ for (const entry of config.nodePathMap) if (Array.isArray(entry?.paths)) paths.push(...entry.paths);
199
+ if (typeof config?.sharedFileSystemPath === 'string') paths.push(config.sharedFileSystemPath);
200
+ return ContainerStorageService.normalizeStorageRoots(paths);
201
+ }
202
+
203
+ /**
204
+ * Builds the command that creates a storage directory only when it is missing.
205
+ *
206
+ * Guarded rather than unconditional: `install -d -m` on an existing tree would rewrite the
207
+ * mode a workload's init container set (MongoDB's `chown 999:999`, MariaDB's data dir), and
208
+ * this runs on every redeploy.
209
+ * @param {string} path - Absolute directory path.
210
+ * @param {{mode?: string, owner?: string, sudo?: boolean}} [options]
211
+ * @returns {string} Shell command.
212
+ */
213
+ static storageDirectoryCommandFactory(
214
+ path,
215
+ { mode = ContainerStorageService.DEFAULT_MODE, owner = '', sudo = true } = {},
216
+ ) {
217
+ if (!path) throw new TypeError('storageDirectoryCommandFactory requires a path');
218
+ const prefix = sudo ? 'sudo ' : '';
219
+ const quoted = shellArgumentFactory(path);
220
+ const ownerFlag = owner
221
+ ? ` -o ${shellArgumentFactory(`${owner}`.split(':')[0])}${
222
+ `${owner}`.includes(':') ? ` -g ${shellArgumentFactory(`${owner}`.split(':')[1])}` : ''
223
+ }`
224
+ : '';
225
+ return `[ -d ${quoted} ] || ${prefix}install -d -m ${mode}${ownerFlag} ${quoted}`;
226
+ }
227
+
228
+ /**
229
+ * Builds the full idempotent preparation for one or more container-mounted storage roots:
230
+ * create when missing, register the persistent `container_file_t` mapping, restore the tree.
231
+ * @param {string|string[]} paths - Absolute directories.
232
+ * @param {{mode?: string, owner?: string, sudo?: boolean}} [options]
233
+ * @returns {string[]} Commands, in execution order.
234
+ */
235
+ static containerStorageCommandsFactory(paths, options = {}) {
236
+ const requested = ContainerStorageService.absoluteStoragePaths(Array.isArray(paths) ? paths : [paths]);
237
+ if (requested.length === 0)
238
+ throw new TypeError('containerStorageCommandsFactory requires at least one absolute path');
239
+ ContainerStorageService.assertSafeStoragePaths(requested);
240
+ // Every requested path is created — a nested one (`/data/mysql`) is a real directory a PV
241
+ // mounts. Mapping and restoring collapse to the covering roots: an fcontext expression is
242
+ // `<root>(/.*)?`, so a nested entry would add a redundant rule to the local policy store and
243
+ // a second full relabel pass over the same tree on every deploy.
244
+ return [
245
+ ...requested.map((path) => ContainerStorageService.storageDirectoryCommandFactory(path, options)),
246
+ ...ContainerStorageService.containerStorageSubtreeCommandsFactory(requested, {
247
+ sudo: options.sudo !== false,
248
+ }),
249
+ ];
250
+ }
251
+
252
+ /**
253
+ * Resolves which declared storage root covers a path.
254
+ * @param {string} path - Absolute path.
255
+ * @param {string[]} [roots] - Candidate roots.
256
+ * @returns {string} The covering root, or the path itself when none covers it.
257
+ */
258
+ static coveringRootFactory(path, roots = ContainerStorageService.PLATFORM_STORAGE_ROOTS) {
259
+ const covering = ContainerStorageService.absoluteStoragePaths(roots)
260
+ .filter((root) => path === root || path.startsWith(`${root}/`))
261
+ .sort((a, b) => b.length - a.length)[0];
262
+ return covering || path;
263
+ }
264
+
265
+ /**
266
+ * Builds the preparation for one subtree of an already-declared storage root: the persistent
267
+ * mapping is registered on the covering root, and only the subtree is restored.
268
+ *
269
+ * A per-volume mapping would grow the local policy store by one `semanage fcontext` rule for
270
+ * every PersistentVolume the deploy flow has ever materialized, and every one of those rules is
271
+ * then evaluated on each relabel. One rule on the root already covers all of them, and it is
272
+ * what makes a volume created later — by kubelet's `DirectoryOrCreate`, or by the local-path
273
+ * helper pod — inherit the right label without another pass.
274
+ * @param {string|string[]} paths - Absolute subtrees to restore.
275
+ * @param {{roots?: string[], mode?: string, owner?: string, sudo?: boolean}} [options]
276
+ * @returns {string[]} Commands, in execution order.
277
+ */
278
+ static containerStorageSubtreeCommandsFactory(paths, { roots, ...options } = {}) {
279
+ const subtrees = ContainerStorageService.absoluteStoragePaths(Array.isArray(paths) ? paths : [paths]);
280
+ if (subtrees.length === 0)
281
+ throw new TypeError('containerStorageSubtreeCommandsFactory requires at least one absolute path');
282
+ const sudo = options.sudo !== false;
283
+ ContainerStorageService.assertSafeStoragePaths(subtrees);
284
+ const mapped = ContainerStorageService.normalizeStorageRoots(
285
+ subtrees.map((path) => ContainerStorageService.coveringRootFactory(path, roots)),
286
+ );
287
+ // The mapped root is what the fcontext rule covers, so it is checked too: a subtree that is
288
+ // itself safe must never resolve up into a root that is not.
289
+ ContainerStorageService.assertSafeStoragePaths(mapped);
290
+ return [
291
+ ...mapped.map((root) =>
292
+ SELinuxService.selinuxFileContextCommandFactory(root, {
293
+ type: ContainerStorageService.SHARED_CONTAINER_TYPE,
294
+ sudo,
295
+ }),
296
+ ),
297
+ SELinuxService.selinuxRestoreconCommandFactory(ContainerStorageService.normalizeStorageRoots(subtrees), {
298
+ sudo,
299
+ }),
300
+ ];
301
+ }
302
+
303
+ /**
304
+ * Executes {@link containerStorageSubtreeCommandsFactory}.
305
+ * @param {string|string[]} paths - Absolute subtrees.
306
+ * @param {{execute: Function, roots?: string[], sudo?: boolean}} options
307
+ * @returns {*[]} Executor results.
308
+ */
309
+ static ensureContainerStorageSubtree(paths, { execute, ...options } = {}) {
310
+ return runSELinuxCommands(ContainerStorageService.containerStorageSubtreeCommandsFactory(paths, options), {
311
+ execute,
312
+ });
313
+ }
314
+
315
+ /**
316
+ * Executes {@link containerStorageCommandsFactory}.
317
+ * @param {string|string[]} paths - Absolute directories.
318
+ * @param {{execute: Function, mode?: string, owner?: string, sudo?: boolean}} options
319
+ * @returns {*[]} Executor results.
320
+ */
321
+ static ensureContainerStorage(paths, { execute, ...options } = {}) {
322
+ return runSELinuxCommands(ContainerStorageService.containerStorageCommandsFactory(paths, options), { execute });
323
+ }
324
+
325
+ /**
326
+ * Command that prints the local-path provisioner `config.json`, or nothing when absent.
327
+ * @param {{namespace: string, configMap?: string}} options
328
+ * @returns {string} Shell command.
329
+ */
330
+ static localPathConfigCommandFactory({ namespace, configMap = ContainerStorageService.LOCAL_PATH_CONFIG_MAP } = {}) {
331
+ if (!namespace) throw new TypeError('localPathConfigCommandFactory requires a namespace');
332
+ return `kubectl get configmap ${configMap} -n ${namespace} -o jsonpath='{.data.config\\.json}' 2>/dev/null || true`;
333
+ }
334
+
335
+ /**
336
+ * Resolves every node directory that must carry the shared container label on this host.
337
+ * @param {{localPathRoots?: string[], extraPaths?: string[], controlPlane?: boolean}} [options]
338
+ * @returns {string[]} Non-overlapping roots.
339
+ */
340
+ static containerStorageRootsFactory({ localPathRoots = [], extraPaths = [], controlPlane = false } = {}) {
341
+ return ContainerStorageService.normalizeStorageRoots([
342
+ ...ContainerStorageService.PLATFORM_STORAGE_ROOTS,
343
+ ...(controlPlane ? ContainerStorageService.CONTROL_PLANE_MOUNT_PATHS : []),
344
+ ...(localPathRoots.length > 0 ? localPathRoots : [ContainerStorageService.LOCAL_PATH_DEFAULT_ROOT]),
345
+ ...extraPaths,
346
+ ]);
347
+ }
348
+ }
349
+
350
+ const {
351
+ absoluteStoragePaths,
352
+ isSafeStoragePath,
353
+ assertSafeStoragePaths,
354
+ containerStorageCommandsFactory,
355
+ containerStorageRootsFactory,
356
+ containerStorageSubtreeCommandsFactory,
357
+ coveringRootFactory,
358
+ ensureContainerStorage,
359
+ ensureContainerStorageSubtree,
360
+ localPathConfigCommandFactory,
361
+ localPathRootsFactory,
362
+ normalizeStorageRoots,
363
+ storageDirectoryCommandFactory,
364
+ } = ContainerStorageService;
365
+
366
+ export default ContainerStorageService;
367
+
368
+ export {
369
+ absoluteStoragePaths,
370
+ isSafeStoragePath,
371
+ assertSafeStoragePaths,
372
+ containerStorageCommandsFactory,
373
+ containerStorageRootsFactory,
374
+ containerStorageSubtreeCommandsFactory,
375
+ coveringRootFactory,
376
+ ensureContainerStorage,
377
+ ensureContainerStorageSubtree,
378
+ localPathConfigCommandFactory,
379
+ localPathRootsFactory,
380
+ normalizeStorageRoots,
381
+ storageDirectoryCommandFactory,
382
+ };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Module for managing crypto operations
3
- * @module src/server/crypto.js
3
+ * @module src/server/security/crypto.js
4
4
  * @namespace Crypto
5
5
  */
6
6
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * SELinux policy, labeling, and enforcement command helpers.
3
3
  *
4
- * @module src/server/selinux.js
4
+ * @module src/server/security/selinux.js
5
5
  * @namespace SELinuxService
6
6
  */
7
7
  'use strict';
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * Manages backup operations for deployments.
3
- * @module src/server/backup.js
3
+ * @module src/server/storage/backup.js
4
4
  * @namespace UnderpostBakcUp
5
5
  */
6
6
 
7
7
  import fs from 'fs-extra';
8
- import { loggerFactory } from './logger.js';
9
- import Underpost from '../index.js';
10
- import { loadCronDeployEnv } from './cron.js';
8
+ import { loggerFactory } from '../ops/logger.js';
9
+ import Underpost from '../../index.js';
10
+ import { loadCronDeployEnv } from '../ops/cron.js';
11
+ import { readDeployRoutes } from '../network/router.js';
11
12
 
12
13
  const logger = loggerFactory(import.meta);
13
14
 
@@ -39,13 +40,13 @@ class BackUp {
39
40
  static callback = async function (deployList, options = { git: false }) {
40
41
  const firstDeployId = deployList && deployList !== 'dd' ? deployList.split(',')[0].trim() : '';
41
42
  loadCronDeployEnv();
42
- if ((!deployList || deployList === 'dd') && fs.existsSync(`./engine-private/deploy/dd.router`))
43
- deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').trim();
43
+ if (!deployList || deployList === 'dd') deployList = readDeployRoutes().join(',');
44
44
 
45
45
  logger.info('init backups callback', deployList);
46
46
  await logger.setUpInfo();
47
47
 
48
48
  const clusterFlag = options.k3s ? ' --k3s' : options.kind ? ' --kind' : options.kubeadm ? ' --kubeadm' : '';
49
+ const failures = [];
49
50
 
50
51
  for (const _deployId of deployList.split(',')) {
51
52
  const deployId = _deployId.trim();
@@ -71,7 +72,8 @@ class BackUp {
71
72
  cd: '/home/dd/engine',
72
73
  });
73
74
  } catch (err) {
74
- logger.error(`Error during database export for ${deployId}:`, err);
75
+ failures.push({ deployId, phase: 'database-export', error: err.message });
76
+ logger.error(`Error during database export for ${deployId}`, { error: err.message });
75
77
  }
76
78
 
77
79
  // Repository backup: Cron container → SSH to host → host finds pod → kubectl exec git backup
@@ -83,9 +85,16 @@ class BackUp {
83
85
  cd: '/home/dd/engine',
84
86
  });
85
87
  } catch (err) {
86
- logger.error(`Error during repository backup for ${deployId}:`, err);
88
+ failures.push({ deployId, phase: 'repository-backup', error: err.message });
89
+ logger.error(`Error during repository backup for ${deployId}`, { error: err.message });
87
90
  }
88
91
  }
92
+
93
+ // One deploy-id failing must not abort the remaining ones, so the loop swallows
94
+ // per-phase errors — this summary is the only place the run's real outcome shows up.
95
+ // The failing `shellExec` has already latched `container-status=error` for monitoring.
96
+ if (failures.length > 0) logger.error('Backup completed with failures', { count: failures.length, failures });
97
+ else logger.info('Backup completed for all deploy-ids', { deployList });
89
98
  };
90
99
  }
91
100
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Module for parsing data query parameters into Mongoose query options.
3
3
  * Supports AG Grid filterModel/sortModel as well as simple legacy parameters.
4
- * @module src/server/data-query.js
4
+ * @module src/server/storage/data-query.js
5
5
  * @namespace DataQuery
6
6
  */
7
7
 
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Provides a utility class for downloading files from a URL and saving them to the local filesystem.
3
- * @module src/server/downloader.js
3
+ * @module src/server/storage/downloader.js
4
4
  * @namespace Downloader
5
5
  */
6
6
 
7
7
  import axios from 'axios';
8
8
  import fs from 'fs';
9
- import { loggerFactory } from './logger.js';
9
+ import { loggerFactory } from '../ops/logger.js';
10
10
 
11
11
  const logger = loggerFactory(import.meta);
12
12
 
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Repository identity: who owns the source this build came from, and the
3
+ * canonical URLs derived from it.
4
+ *
5
+ * Every environment publishes from a different fork, so an owner baked into a
6
+ * component renders a link to someone else's repository. The owner is resolved
7
+ * once here, travels to the client in `renderPayload.repository`, and is the
8
+ * only thing any GitHub, Pages or Coveralls URL is composed from.
9
+ *
10
+ * @module src/server/storage/repository.js
11
+ * @namespace ServerRepository
12
+ */
13
+
14
+ import { environmentValueFactory } from '../runtime/environment.js';
15
+
16
+ /**
17
+ * @constant REPOSITORY_DEFAULTS
18
+ * @description Fallbacks for a tree published without repository environment.
19
+ * The only place in the codebase allowed to name an owner or a repository.
20
+ * @memberof ServerRepository
21
+ */
22
+ const REPOSITORY_DEFAULTS = {
23
+ owner: 'underpostnet',
24
+ name: 'engine',
25
+ template: 'pwa-microservices-template',
26
+ // Prebuilt package repositories are the template repository plus this suffix.
27
+ packageSuffix: '-ghpkg',
28
+ };
29
+
30
+ /**
31
+ * @method repositoryIdentityFactory
32
+ * @description Resolves the repository identity this build publishes under.
33
+ * @param {object} [overrides] - Explicit values that win over the environment.
34
+ * @returns {{owner: string, name: string, template: string, packageSuffix: string}} Identity.
35
+ * @memberof ServerRepository
36
+ */
37
+ const repositoryIdentityFactory = (overrides = {}) => ({
38
+ ...REPOSITORY_DEFAULTS,
39
+ ...(environmentValueFactory('GITHUB_USERNAME') ? { owner: environmentValueFactory('GITHUB_USERNAME') } : {}),
40
+ ...Object.fromEntries(Object.entries(overrides).filter(([, value]) => value)),
41
+ });
42
+
43
+ /**
44
+ * @method githubUrlFactory
45
+ * @description Composes a github.com URL under the resolved owner.
46
+ * @param {object} [params]
47
+ * @param {object} [params.identity] - Identity to compose against.
48
+ * @param {string[]} [params.segments] - Path segments after the owner.
49
+ * @returns {string} Absolute URL, trailing slash included.
50
+ * @memberof ServerRepository
51
+ */
52
+ const githubUrlFactory = ({ identity = repositoryIdentityFactory(), segments = [] } = {}) =>
53
+ `https://github.com/${[identity.owner, ...segments].filter(Boolean).join('/')}/`;
54
+
55
+ /**
56
+ * @method githubCommitUrlFactory
57
+ * @description Markdown link to one commit, for generated changelogs.
58
+ * @param {object} params
59
+ * @param {string} params.shortHash - Abbreviated hash used as the link text.
60
+ * @param {string} params.hash - Full hash the link resolves to.
61
+ * @param {object} [params.identity] - Identity to compose against.
62
+ * @returns {string} Markdown link.
63
+ * @memberof ServerRepository
64
+ */
65
+ const githubCommitUrlFactory = ({ shortHash, hash, identity = repositoryIdentityFactory() }) =>
66
+ `[${shortHash}](https://github.com/${identity.owner}/${identity.name}/commit/${hash})`;
67
+
68
+ export { REPOSITORY_DEFAULTS, githubCommitUrlFactory, githubUrlFactory, repositoryIdentityFactory };
package/src/server.js CHANGED
@@ -1,14 +1,11 @@
1
1
  'use strict';
2
2
 
3
- // https://nodejs.org/api
4
- // https://expressjs.com/en/4x/api.html
5
-
6
3
  import dotenv from 'dotenv';
7
- import { loggerFactory } from './server/logger.js';
4
+ import { loggerFactory } from './server/ops/logger.js';
8
5
  import { buildClient } from './client-builder/client-build.js';
9
- import { buildRuntime } from './server/runtime.js';
10
- import { ProcessController } from './server/process.js';
11
- import { Config } from './server/conf.js';
6
+ import { buildRuntime } from './server/runtime/runtime.js';
7
+ import { ProcessController } from './server/runtime/process.js';
8
+ import { Config } from './server/runtime/conf.js';
12
9
 
13
10
  dotenv.config();
14
11
 
@@ -4,7 +4,7 @@
4
4
  * @namespace SocketIoInterface
5
5
  */
6
6
 
7
- import { loggerFactory } from '../server/logger.js';
7
+ import { loggerFactory } from '../server/ops/logger.js';
8
8
  import { Socket } from 'socket.io';
9
9
 
10
10
  const logger = loggerFactory(import.meta);
@@ -6,7 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  import { Server } from 'socket.io';
9
- import { loggerFactory } from '../server/logger.js';
9
+ import { loggerFactory } from '../server/ops/logger.js';
10
10
  import Underpost from '../index.js';
11
11
 
12
12
  const logger = loggerFactory(import.meta);
@@ -3,7 +3,7 @@
3
3
  * @module ws/core/core.ws.connection
4
4
  */
5
5
 
6
- import { loggerFactory } from '../../server/logger.js';
6
+ import { loggerFactory } from '../../server/ops/logger.js';
7
7
  import { CoreWsChatChannel } from './channels/core.ws.chat.js';
8
8
  import { CoreWsMailerChannel } from './channels/core.ws.mailer.js';
9
9
  import { CoreWsStreamChannel } from './channels/core.ws.stream.js';
@@ -3,7 +3,7 @@
3
3
  * @module ws/core/core.ws.emit
4
4
  */
5
5
 
6
- import { loggerFactory } from '../../server/logger.js';
6
+ import { loggerFactory } from '../../server/ops/logger.js';
7
7
 
8
8
  const logger = loggerFactory(import.meta);
9
9
 
@@ -10,7 +10,7 @@ import { CoreWsConnectionHandler } from './core.ws.connection.js';
10
10
  import { CoreWsChatChannel } from './channels/core.ws.chat.js';
11
11
  import { CoreWsMailerChannel } from './channels/core.ws.mailer.js';
12
12
  import { CoreWsStreamChannel } from './channels/core.ws.stream.js';
13
- import { resolveHostKeyContext } from '../../server/conf.js';
13
+ import { resolveHostKeyContext } from '../../server/runtime/conf.js';
14
14
 
15
15
  /**
16
16
  * @class CoreWsServer
@@ -3,7 +3,7 @@
3
3
  * @module ws/default/default.ws.connection
4
4
  */
5
5
 
6
- import { loggerFactory } from '../../server/logger.js';
6
+ import { loggerFactory } from '../../server/ops/logger.js';
7
7
  import { DefaultWsMainChannel } from './channels/default.ws.main.js';
8
8
 
9
9
  const logger = loggerFactory(import.meta);
@@ -1,4 +1,4 @@
1
- import { loggerFactory } from '../../server/logger.js';
1
+ import { loggerFactory } from '../../server/ops/logger.js';
2
2
 
3
3
  const logger = loggerFactory(import.meta);
4
4
 
@@ -8,7 +8,7 @@
8
8
  import { IoServer } from '../IoServer.js';
9
9
  import { DefaultWsConnectionHandler } from './default.ws.connection.js';
10
10
  import { DefaultWsMainChannel } from './channels/default.ws.main.js';
11
- import { resolveHostKeyContext } from '../../server/conf.js';
11
+ import { resolveHostKeyContext } from '../../server/runtime/conf.js';
12
12
 
13
13
  /**
14
14
  * @class DefaultWsServer