@underpostnet/cyberia 3.2.90 → 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 (490) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +16 -0
  3. package/.github/workflows/coverall.cyberia.ci.yml +107 -0
  4. package/.github/workflows/cyberia-client.cd.yml +6 -18
  5. package/.github/workflows/cyberia-server.cd.yml +6 -18
  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 +6 -78
  13. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  14. package/.github/workflows/ghpkg.ci.yml +42 -21
  15. package/.github/workflows/hardhat.ci.yml +12 -11
  16. package/.github/workflows/npmpkg.ci.yml +17 -15
  17. package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
  18. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  19. package/.github/workflows/release.cd.yml +2 -9
  20. package/.prettierignore +1 -0
  21. package/AGENTS.md +47 -0
  22. package/CHANGELOG.md +581 -2417
  23. package/CLI-HELP.md +416 -127
  24. package/Dockerfile +25 -9
  25. package/Dockerfile.dev +25 -9
  26. package/Dockerfile.test +4 -4
  27. package/README.md +21 -1
  28. package/bin/build.js +70 -43
  29. package/bin/build.template.js +8 -3
  30. package/bin/cyberia.js +372 -135
  31. package/bin/deploy.js +18 -104
  32. package/bin/index.js +372 -135
  33. package/compose.env +16 -0
  34. package/conf.js +93 -4
  35. package/deploy/cyberia-client/deploy.sh +47 -0
  36. package/deploy/cyberia-client/package.sh +18 -0
  37. package/deploy/cyberia-client/state.sh +14 -0
  38. package/deploy/cyberia-server/deploy.sh +47 -0
  39. package/deploy/cyberia-server/package.sh +18 -0
  40. package/deploy/cyberia-server/state.sh +14 -0
  41. package/deploy/dd-cyberia/deploy.sh +22 -0
  42. package/deploy/dd-cyberia/init.sh +55 -0
  43. package/deploy/dd-cyberia/package.sh +17 -0
  44. package/deploy/dd-cyberia/state.sh +14 -0
  45. package/deploy/dd-cyberia/sync-deploy.sh +116 -0
  46. package/deploy/lib/github-actions-logging.sh +594 -0
  47. package/deploy/lib/host.sh +185 -0
  48. package/deploy/lib/state.sh +62 -0
  49. package/deploy/pwa-microservices-template/deploy.sh +45 -0
  50. package/deploy/release/deploy.sh +32 -0
  51. package/deployment.yaml +7 -2
  52. package/docker-compose.yml +31 -37
  53. package/examples/static-page/README.md +19 -19
  54. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  55. package/hardhat/hardhat.config.js +1 -6
  56. package/hardhat/package-lock.json +104 -43
  57. package/hardhat/package.json +3 -3
  58. package/manifests/alertmanager/deployment.yaml +81 -0
  59. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  60. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +36 -7
  61. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +77 -0
  62. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  63. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  64. package/manifests/grafana/deployment.yaml +26 -7
  65. package/manifests/grafana/kustomization.yaml +1 -0
  66. package/manifests/grafana/service.yaml +6 -1
  67. package/manifests/mariadb/pv.yaml +1 -0
  68. package/manifests/mongodb/statefulset.yaml +9 -2
  69. package/manifests/mysql/pv-pvc.yaml +14 -1
  70. package/manifests/postgresql/pv.yaml +12 -1
  71. package/manifests/postgresql/pvc.yaml +1 -0
  72. package/manifests/prometheus/deployment.yaml +18 -22
  73. package/package.json +83 -10
  74. package/scripts/audit-selinux.sh +64 -0
  75. package/scripts/event-monitor.sh +56 -0
  76. package/scripts/gpu-diag.sh +0 -0
  77. package/scripts/ip-info.sh +0 -0
  78. package/scripts/k3s-node-setup.sh +30 -14
  79. package/scripts/kubeadm-node-setup.sh +40 -31
  80. package/scripts/lxd-vm-setup.sh +0 -0
  81. package/scripts/maas-nat-firewalld.sh +0 -0
  82. package/scripts/maas-setup.sh +8 -8
  83. package/scripts/nat-iptables.sh +2 -0
  84. package/scripts/rhel-grpc-setup.sh +0 -0
  85. package/scripts/rocky-kickstart.sh +25 -9
  86. package/scripts/selinux-normalize.sh +907 -0
  87. package/scripts/shutdown-machine.sh +843 -0
  88. package/scripts/test-monitor.sh +3 -3
  89. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
  90. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
  91. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
  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 +1 -1
  99. package/src/api/cyberia-action/cyberia-action.service.js +2 -2
  100. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
  101. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
  102. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
  103. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  104. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
  105. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  106. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  107. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  108. package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
  109. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
  110. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
  111. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
  112. package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
  113. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +63 -0
  114. package/src/api/cyberia-instance/cyberia-fallback-world.js +16 -1
  115. package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
  116. package/src/api/cyberia-instance/cyberia-instance.controller.js +4 -1
  117. package/src/api/cyberia-instance/cyberia-instance.router.js +15 -2
  118. package/src/api/cyberia-instance/cyberia-instance.service.js +45 -2
  119. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  120. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +1 -0
  121. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  122. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
  123. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  124. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  125. package/src/api/cyberia-map/cyberia-map.service.js +2 -2
  126. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  127. package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
  128. package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
  129. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  130. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  131. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  132. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  133. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  134. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  135. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +16 -29
  136. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  137. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  138. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  139. package/src/api/default/default.controller.js +1 -1
  140. package/src/api/default/default.router.js +1 -1
  141. package/src/api/default/default.service.js +2 -2
  142. package/src/api/document/document.controller.js +1 -1
  143. package/src/api/document/document.router.js +1 -1
  144. package/src/api/document/document.service.js +2 -2
  145. package/src/api/file/file.controller.js +1 -1
  146. package/src/api/file/file.router.js +1 -1
  147. package/src/api/file/file.service.js +2 -2
  148. package/src/api/instance/instance.controller.js +1 -1
  149. package/src/api/instance/instance.router.js +1 -1
  150. package/src/api/instance/instance.service.js +2 -2
  151. package/src/api/ipfs/ipfs.controller.js +1 -1
  152. package/src/api/ipfs/ipfs.router.js +2 -2
  153. package/src/api/ipfs/ipfs.service.js +2 -2
  154. package/src/api/object-layer/object-layer.controller.js +1 -1
  155. package/src/api/object-layer/object-layer.model.js +204 -3
  156. package/src/api/object-layer/object-layer.router.js +2 -2
  157. package/src/api/object-layer/object-layer.service.js +4 -17
  158. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  159. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  160. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  161. package/src/api/test/test.controller.js +1 -1
  162. package/src/api/test/test.service.js +1 -1
  163. package/src/api/user/guest.service.js +3 -3
  164. package/src/api/user/user.controller.js +1 -1
  165. package/src/api/user/user.router.js +2 -2
  166. package/src/api/user/user.service.js +4 -4
  167. package/src/api.js +5 -9
  168. package/src/cli/app.js +391 -0
  169. package/src/cli/baremetal.js +30 -36
  170. package/src/cli/client.js +306 -0
  171. package/src/cli/cloud-init.js +3 -3
  172. package/src/cli/cluster.js +242 -135
  173. package/src/cli/db.js +126 -67
  174. package/src/cli/deploy.js +158 -60
  175. package/src/cli/docker-compose.js +5 -5
  176. package/src/cli/domains.js +184 -0
  177. package/src/cli/dotenv-store.js +143 -0
  178. package/src/cli/event.js +2281 -0
  179. package/src/cli/fs.js +3 -3
  180. package/src/cli/host.js +672 -0
  181. package/src/cli/image.js +4 -7
  182. package/src/cli/index.js +426 -134
  183. package/src/cli/ipfs.js +34 -30
  184. package/src/cli/kickstart.js +1 -1
  185. package/src/cli/kubectl.js +218 -41
  186. package/src/cli/lxd.js +3 -3
  187. package/src/cli/monitor.js +1359 -26
  188. package/src/cli/package.js +90 -0
  189. package/src/cli/release.js +73 -34
  190. package/src/cli/repository.js +564 -367
  191. package/src/cli/run.js +362 -654
  192. package/src/cli/secrets.js +2158 -964
  193. package/src/cli/ssh.js +651 -331
  194. package/src/cli/state.js +394 -0
  195. package/src/cli/static.js +2 -2
  196. package/src/cli/system.js +26 -13
  197. package/src/cli/test.js +199 -125
  198. package/src/cli/vultr.js +623 -0
  199. package/src/cli/wireguard.js +2930 -0
  200. package/src/client/components/core/CalendarCore.js +53 -96
  201. package/src/client/components/core/Docs.js +258 -211
  202. package/src/client/components/core/FileExplorer.js +0 -21
  203. package/src/client/components/core/PanelForm.js +4 -4
  204. package/src/client/components/core/Repository.js +56 -0
  205. package/src/client/components/core/Translate.js +7 -0
  206. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  207. package/src/client/components/core/Wallet.js +0 -11
  208. package/src/client/components/core/Worker.js +7 -1
  209. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  210. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +368 -0
  211. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +35 -1
  212. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +4 -0
  213. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  214. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
  215. package/src/client/components/default/AppShellDefault.js +1 -1
  216. package/src/client/components/default/SettingsDefault.js +2 -2
  217. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  218. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  219. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  220. package/src/client/public/cyberia-docs/ARCHITECTURE.md +17 -3
  221. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
  222. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +1 -1
  223. package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
  224. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  225. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  226. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  227. package/src/client/public/default/android-chrome-144x144.png +0 -0
  228. package/src/client/public/default/android-chrome-192x192.png +0 -0
  229. package/src/client/public/default/android-chrome-256x256.png +0 -0
  230. package/src/client/public/default/android-chrome-36x36.png +0 -0
  231. package/src/client/public/default/android-chrome-384x384.png +0 -0
  232. package/src/client/public/default/android-chrome-48x48.png +0 -0
  233. package/src/client/public/default/android-chrome-512x512.png +0 -0
  234. package/src/client/public/default/android-chrome-72x72.png +0 -0
  235. package/src/client/public/default/android-chrome-96x96.png +0 -0
  236. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  237. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  238. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  239. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  240. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  241. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  242. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  243. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  244. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  245. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  246. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  247. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  248. package/src/client/public/default/apple-touch-icon.png +0 -0
  249. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  250. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  251. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  252. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  253. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  254. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  255. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  256. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  257. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  258. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  259. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  260. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  261. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  262. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  263. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  264. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  265. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  266. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  267. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  268. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  269. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  270. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  271. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  272. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  273. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  274. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  275. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  276. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  277. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  278. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  279. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  280. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  281. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  282. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  283. package/src/client/public/default/assets/background/white.jpg +0 -0
  284. package/src/client/public/default/browserconfig.xml +1 -1
  285. package/src/client/public/default/favicon-16x16.png +0 -0
  286. package/src/client/public/default/favicon-32x32.png +0 -0
  287. package/src/client/public/default/favicon-48x48.png +0 -0
  288. package/src/client/public/default/favicon.ico +0 -0
  289. package/src/client/public/default/manifest.webmanifest +5 -5
  290. package/src/client/public/default/mstile-144x144.png +0 -0
  291. package/src/client/public/default/mstile-150x150.png +0 -0
  292. package/src/client/public/default/mstile-310x150.png +0 -0
  293. package/src/client/public/default/mstile-310x310.png +0 -0
  294. package/src/client/public/default/mstile-70x70.png +0 -0
  295. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  296. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  297. package/src/client/services/cyberia-instance/cyberia-instance.service.js +40 -0
  298. package/src/client/services/object-layer/object-layer.management.js +4 -4
  299. package/src/client/ssr/RootDocument.js +1 -1
  300. package/src/client/ssr/body/404.js +1 -1
  301. package/src/client/ssr/body/500.js +1 -1
  302. package/src/client/ssr/body/CacheControl.js +1 -1
  303. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  304. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  305. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  306. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  307. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  308. package/src/client/ssr/head/Css.js +1 -1
  309. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  310. package/src/client/ssr/head/DefaultScripts.js +1 -1
  311. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  312. package/src/client/ssr/head/Microdata.js +1 -1
  313. package/src/client/ssr/head/Production.js +1 -1
  314. package/src/client/ssr/head/Pwa.js +1 -1
  315. package/src/client/ssr/head/PwaItemledger.js +1 -1
  316. package/src/client/ssr/head/Seo.js +1 -1
  317. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  318. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  319. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  320. package/src/client/ssr/views/Cyberia404.js +7 -5
  321. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  322. package/src/client/ssr/views/Maintenance.js +1 -1
  323. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  324. package/src/client/ssr/views/Test.js +1 -1
  325. package/src/client/sw/core.sw.js +20 -14
  326. package/src/client-builder/client-build-docs.js +61 -46
  327. package/src/client-builder/client-build-live.js +2 -2
  328. package/src/client-builder/client-build.js +58 -44
  329. package/src/client-builder/client-dev-server.js +3 -3
  330. package/src/client-builder/client-icons.js +2 -2
  331. package/src/client-builder/ssr.js +3 -3
  332. package/src/client.build.js +3 -6
  333. package/src/client.dev.js +3 -6
  334. package/src/db/DataBaseProvider.js +186 -3
  335. package/src/db/mariadb/MariaDB.js +3 -2
  336. package/src/db/mongo/MongoBootstrap.js +273 -101
  337. package/src/db/mongo/MongooseDB.js +11 -8
  338. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  339. package/src/grpc/cyberia/grpc-server.js +1 -1
  340. package/src/index.js +103 -23
  341. package/src/mailer/EmailRender.js +2 -2
  342. package/src/mailer/MailerInterceptor.js +87 -0
  343. package/src/mailer/MailerProvider.js +50 -6
  344. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
  345. package/src/projects/cyberia/besu-genesis-generator.js +3 -3
  346. package/src/projects/cyberia/catalog-cyberia.js +54 -6
  347. package/src/projects/cyberia/gemini-client.js +1 -1
  348. package/src/projects/cyberia/generate-saga.js +15 -24
  349. package/src/projects/cyberia/hot-reload-trigger.js +1 -1
  350. package/src/projects/cyberia/instance-data.js +22 -3
  351. package/src/projects/cyberia/ipfs-client.js +4 -4
  352. package/src/projects/cyberia/map-preview-generator.js +1 -1
  353. package/src/projects/cyberia/object-layer.js +12 -22
  354. package/src/projects/cyberia/semantic-layer-generator.js +1 -1
  355. package/src/projects/underpost/catalog-underpost.js +13 -2
  356. package/src/proxy.js +4 -7
  357. package/src/runtime/cyberia-client/Dockerfile +9 -4
  358. package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
  359. package/src/runtime/cyberia-server/Dockerfile +9 -4
  360. package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
  361. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  362. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  363. package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
  364. package/src/runtime/engine-cyberia/compose.env +16 -0
  365. package/src/runtime/engine-cyberia/docker-compose.yml +31 -37
  366. package/src/runtime/express/Express.js +32 -27
  367. package/src/runtime/lampp/Lampp.js +22 -70
  368. package/src/runtime/nginx/Nginx.js +1 -1
  369. package/src/runtime/wp/Wp.js +16 -48
  370. package/src/server/{catalog.js → build/catalog.js} +15 -5
  371. package/src/server/build/coverage.js +117 -0
  372. package/src/server/build/execution.js +402 -0
  373. package/src/server/build/package.js +465 -0
  374. package/src/server/build/testing.js +528 -0
  375. package/src/server/{dns.js → network/dns.js} +241 -14
  376. package/src/server/network/forward-proxy.js +541 -0
  377. package/src/server/{middlewares.js → network/middlewares.js} +59 -4
  378. package/src/server/network/node-capability.js +98 -0
  379. package/src/server/{peer.js → network/peer.js} +3 -3
  380. package/src/server/{proxy.js → network/proxy.js} +7 -13
  381. package/src/server/network/router.js +356 -0
  382. package/src/server/{tls.js → network/tls.js} +2 -2
  383. package/src/server/network/underpost-compression.js +186 -0
  384. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +26 -16
  385. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +19 -3
  386. package/src/server/{cri.js → ops/cri.js} +2 -2
  387. package/src/server/ops/cron.js +949 -0
  388. package/src/server/ops/event-notification.js +284 -0
  389. package/src/server/{logger.js → ops/logger.js} +108 -23
  390. package/src/server/ops/monitoring.js +1724 -0
  391. package/src/server/ops/systemd.js +259 -0
  392. package/src/server/{conf.js → runtime/conf.js} +521 -520
  393. package/src/server/runtime/config-scope.js +215 -0
  394. package/src/server/runtime/environment.js +149 -0
  395. package/src/server/{process.js → runtime/process.js} +153 -13
  396. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  397. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  398. package/src/server/{start.js → runtime/start.js} +128 -39
  399. package/src/server/{auth.js → security/auth.js} +7 -8
  400. package/src/server/security/container-storage.js +382 -0
  401. package/src/server/{crypto.js → security/crypto.js} +1 -1
  402. package/src/server/security/selinux.js +185 -0
  403. package/src/server/{backup.js → storage/backup.js} +17 -8
  404. package/src/server/{data-query.js → storage/data-query.js} +1 -1
  405. package/src/server/{downloader.js → storage/downloader.js} +2 -2
  406. package/src/server/storage/repository.js +68 -0
  407. package/src/server.js +4 -7
  408. package/src/ws/IoInterface.js +1 -1
  409. package/src/ws/IoServer.js +1 -1
  410. package/src/ws/core/core.ws.connection.js +1 -1
  411. package/src/ws/core/core.ws.emit.js +1 -1
  412. package/src/ws/core/core.ws.server.js +1 -1
  413. package/src/ws/default/default.ws.connection.js +1 -1
  414. package/src/ws/default/default.ws.emit.js +1 -1
  415. package/src/ws/default/default.ws.server.js +1 -1
  416. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  417. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  418. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  419. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  420. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
  421. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +2 -1
  422. package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
  423. package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
  424. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  425. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  426. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  427. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  428. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  429. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  430. package/test/integration/infra/1-security/selinux.test.js +69 -0
  431. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  432. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  433. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  434. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  435. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  436. package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
  437. package/test/integration/infra/2-network/wireguard-edge.test.js +1731 -0
  438. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  439. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  440. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  441. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  442. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  443. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  444. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +47 -6
  445. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +56 -4
  446. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  447. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  448. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  449. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  450. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  451. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  452. package/test/support/shell-harness.js +73 -0
  453. package/test/unit/build-template.test.js +97 -0
  454. package/test/unit/build-workflow-offline.test.js +132 -0
  455. package/test/unit/catalog.test.js +71 -0
  456. package/test/unit/client-build-docs.test.js +334 -0
  457. package/test/unit/conf-loading.test.js +303 -0
  458. package/test/unit/conf-resolution.test.js +979 -0
  459. package/test/unit/coverage-artifact.test.js +130 -0
  460. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  461. package/test/unit/deploy-env-resolution.test.js +38 -0
  462. package/test/unit/deploy-log-table.test.js +447 -0
  463. package/test/unit/execution-profiles.test.js +219 -0
  464. package/test/unit/fleet-sync-source.test.js +149 -0
  465. package/test/unit/logger-redaction.test.js +112 -0
  466. package/test/unit/package.test.js +403 -0
  467. package/test/unit/prepare-host.test.js +299 -0
  468. package/test/unit/process-environment.test.js +18 -0
  469. package/test/unit/propagation-message.test.js +78 -0
  470. package/test/unit/redeploy-plan.test.js +24 -0
  471. package/test/unit/release-bump.test.js +474 -0
  472. package/test/unit/ssh-output-redaction.test.js +28 -0
  473. package/test/unit/start-options.test.js +46 -0
  474. package/test/unit/test-tiers.test.js +193 -0
  475. package/vitest.config.js +58 -0
  476. package/.nycrc +0 -9
  477. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  478. package/manifests/mongodb/pv-pvc.yaml +0 -59
  479. package/scripts/link-local-underpost-cli.sh +0 -6
  480. package/src/api/user/user.build.js +0 -16
  481. package/src/cli/env.js +0 -177
  482. package/src/client/components/core/Blockchain.js +0 -41
  483. package/src/client/components/core/Blog.js +0 -9
  484. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  485. package/src/client/public/default/assets/background/dark.jpg +0 -0
  486. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  487. package/src/client/public/default/assets/background/white0.jpg +0 -0
  488. package/src/client/public/doc/favicon.ico +0 -0
  489. package/src/client/public/doc/sitemap +0 -148
  490. package/src/server/cron.js +0 -476
@@ -4,36 +4,6 @@
4
4
  # (MongoDB + Valkey + IPFS), then the Cyberia content-authority engine and its
5
5
  # per-instance server/client tiers, fronted by an nginx reverse proxy.
6
6
  #
7
- # Canonical location (custom docker-compose workflow):
8
- # engine-private/conf/dd-cyberia/docker-compose/cyberia/
9
- # ├── docker-compose.yml (this file — the ENTIRE stack, single source)
10
- # ├── compose.env (working env-file, used as-is — not generated)
11
- # ├── nginx.conf (custom per-variant sub-path routing)
12
- # └── mongodb/entrypoint.sh (replica-set bootstrap)
13
- # All bind mounts below are relative to this directory: the CLI runs compose with
14
- # `--project-directory` pinned here (see src/cli/docker-compose.js).
15
- #
16
- # Multi-instance: one engine-cyberia (content + asset authority) feeds three
17
- # cyberia-server + three cyberia-client tiers, one per conf.instances.json
18
- # multiInstance variant (amethyst-strata-expansion "/", FOREST "/FOREST",
19
- # TEST "/TEST"). This custom workflow owns nginx.conf and the services below;
20
- # keep both in sync when its instance topology changes.
21
- #
22
- # Startup is a strict health-gated chain: the stable gateway starts after the
23
- # engine, then each server/client pipeline advances independently:
24
- # mongodb + valkey -> engine runtime -> proxy -> 3x server -> 3x client
25
- #
26
- # Architecture boundaries (see CLAUDE.md "Cyberia architecture boundaries"):
27
- # engine-cyberia — content, validation, persistence, gRPC(:50051)+REST(:4005)
28
- # data services, asset metadata. The authority layer.
29
- # cyberia-server — authoritative real-time simulation / tick processing (Go).
30
- # cyberia-client — rendering, input, prediction, presentation (WASM bundle).
31
- #
32
- # Usage:
33
- # underpost docker-compose --up --deploy-id dd-cyberia --docker-compose-id cyberia
34
- # (or the docker:cyberia:* npm scripts). The engine-cyberia image bakes the
35
- # dd-cyberia build at image-build time, so no private-repo credentials are
36
- # required at container start.
37
7
 
38
8
  name: dd-cyberia
39
9
 
@@ -165,7 +135,7 @@ services:
165
135
  # server starts but rejects connections until seeded). Serves REST/WS on 4005
166
136
  # and the engine gRPC data service on 50051.
167
137
  engine-cyberia-runtime:
168
- image: ${ENGINE_CYBERIA_IMAGE:-underpost/engine-cyberia-dev}:${ENGINE_CYBERIA_TAG:-v3.2.90}
138
+ image: ${ENGINE_CYBERIA_IMAGE:-underpost/engine-cyberia-dev}:${ENGINE_CYBERIA_TAG:-v3.3.73}
169
139
  container_name: dd-cyberia-engine
170
140
  command:
171
141
  - /bin/sh
@@ -220,7 +190,7 @@ services:
220
190
  # gateway on host port 8081, so one port can route every instance path.
221
191
 
222
192
  cyberia-server-runtime:
223
- image: ${CYBERIA_SERVER_IMAGE:-underpost/cyberia-server-dev}:${CYBERIA_SERVER_TAG:-v3.2.90}
193
+ image: ${CYBERIA_SERVER_IMAGE:-underpost/cyberia-server-dev}:${CYBERIA_SERVER_TAG:-v3.3.73}
224
194
  container_name: dd-cyberia-server
225
195
  environment:
226
196
  INSTANCE_CODE: amethyst-strata-expansion
@@ -232,6 +202,14 @@ services:
232
202
  STATIC_DIR: ${CYBERIA_SERVER_STATIC_DIR:-/home/dd/engine/cyberia-server/public}
233
203
  APP_ENV: ${CYBERIA_SERVER_APP_ENV:-development}
234
204
  LOG_LEVEL: ${CYBERIA_SERVER_LOG_LEVEL:-}
205
+ CYBERIA_DISABLE_CONNECTION_LIMITS: ${CYBERIA_DISABLE_CONNECTION_LIMITS:-}
206
+ CYBERIA_MAX_CONNECTIONS: ${CYBERIA_MAX_CONNECTIONS:-}
207
+ CYBERIA_MAX_CONNECTIONS_PER_IP: ${CYBERIA_MAX_CONNECTIONS_PER_IP:-}
208
+ CYBERIA_CONNECT_RATE_PER_IP: ${CYBERIA_CONNECT_RATE_PER_IP:-}
209
+ CYBERIA_CONNECT_BURST_PER_IP: ${CYBERIA_CONNECT_BURST_PER_IP:-}
210
+ CYBERIA_MESSAGE_RATE: ${CYBERIA_MESSAGE_RATE:-}
211
+ CYBERIA_MESSAGE_BURST: ${CYBERIA_MESSAGE_BURST:-}
212
+ CYBERIA_MAX_STRIKES: ${CYBERIA_MAX_STRIKES:-}
235
213
  networks:
236
214
  - dd-cyberia-internal
237
215
  expose:
@@ -248,7 +226,7 @@ services:
248
226
  restart: unless-stopped
249
227
 
250
228
  cyberia-server-forest:
251
- image: ${CYBERIA_SERVER_IMAGE:-underpost/cyberia-server-dev}:${CYBERIA_SERVER_TAG:-v3.2.90}
229
+ image: ${CYBERIA_SERVER_IMAGE:-underpost/cyberia-server-dev}:${CYBERIA_SERVER_TAG:-v3.3.73}
252
230
  container_name: dd-cyberia-server-forest
253
231
  environment:
254
232
  INSTANCE_CODE: FOREST
@@ -260,6 +238,14 @@ services:
260
238
  STATIC_DIR: ${CYBERIA_SERVER_STATIC_DIR:-/home/dd/engine/cyberia-server/public}
261
239
  APP_ENV: ${CYBERIA_SERVER_APP_ENV:-development}
262
240
  LOG_LEVEL: ${CYBERIA_SERVER_LOG_LEVEL:-}
241
+ CYBERIA_DISABLE_CONNECTION_LIMITS: ${CYBERIA_DISABLE_CONNECTION_LIMITS:-}
242
+ CYBERIA_MAX_CONNECTIONS: ${CYBERIA_MAX_CONNECTIONS:-}
243
+ CYBERIA_MAX_CONNECTIONS_PER_IP: ${CYBERIA_MAX_CONNECTIONS_PER_IP:-}
244
+ CYBERIA_CONNECT_RATE_PER_IP: ${CYBERIA_CONNECT_RATE_PER_IP:-}
245
+ CYBERIA_CONNECT_BURST_PER_IP: ${CYBERIA_CONNECT_BURST_PER_IP:-}
246
+ CYBERIA_MESSAGE_RATE: ${CYBERIA_MESSAGE_RATE:-}
247
+ CYBERIA_MESSAGE_BURST: ${CYBERIA_MESSAGE_BURST:-}
248
+ CYBERIA_MAX_STRIKES: ${CYBERIA_MAX_STRIKES:-}
263
249
  networks:
264
250
  - dd-cyberia-internal
265
251
  expose:
@@ -276,7 +262,7 @@ services:
276
262
  restart: unless-stopped
277
263
 
278
264
  cyberia-server-test:
279
- image: ${CYBERIA_SERVER_IMAGE:-underpost/cyberia-server-dev}:${CYBERIA_SERVER_TAG:-v3.2.90}
265
+ image: ${CYBERIA_SERVER_IMAGE:-underpost/cyberia-server-dev}:${CYBERIA_SERVER_TAG:-v3.3.73}
280
266
  container_name: dd-cyberia-server-test
281
267
  environment:
282
268
  INSTANCE_CODE: TEST
@@ -288,6 +274,14 @@ services:
288
274
  STATIC_DIR: ${CYBERIA_SERVER_STATIC_DIR:-/home/dd/engine/cyberia-server/public}
289
275
  APP_ENV: ${CYBERIA_SERVER_APP_ENV:-development}
290
276
  LOG_LEVEL: ${CYBERIA_SERVER_LOG_LEVEL:-}
277
+ CYBERIA_DISABLE_CONNECTION_LIMITS: ${CYBERIA_DISABLE_CONNECTION_LIMITS:-}
278
+ CYBERIA_MAX_CONNECTIONS: ${CYBERIA_MAX_CONNECTIONS:-}
279
+ CYBERIA_MAX_CONNECTIONS_PER_IP: ${CYBERIA_MAX_CONNECTIONS_PER_IP:-}
280
+ CYBERIA_CONNECT_RATE_PER_IP: ${CYBERIA_CONNECT_RATE_PER_IP:-}
281
+ CYBERIA_CONNECT_BURST_PER_IP: ${CYBERIA_CONNECT_BURST_PER_IP:-}
282
+ CYBERIA_MESSAGE_RATE: ${CYBERIA_MESSAGE_RATE:-}
283
+ CYBERIA_MESSAGE_BURST: ${CYBERIA_MESSAGE_BURST:-}
284
+ CYBERIA_MAX_STRIKES: ${CYBERIA_MAX_STRIKES:-}
291
285
  networks:
292
286
  - dd-cyberia-internal
293
287
  expose:
@@ -315,7 +309,7 @@ services:
315
309
  # cyberia-server-test -> cyberia-client-test
316
310
 
317
311
  cyberia-client-runtime:
318
- image: ${CYBERIA_CLIENT_IMAGE:-underpost/cyberia-client-dev}:${CYBERIA_CLIENT_TAG:-v3.2.90}
312
+ image: ${CYBERIA_CLIENT_IMAGE:-underpost/cyberia-client-dev}:${CYBERIA_CLIENT_TAG:-v3.3.73}
319
313
  container_name: dd-cyberia-client
320
314
  environment:
321
315
  CYBERIA_PORT: '8081'
@@ -340,7 +334,7 @@ services:
340
334
  restart: unless-stopped
341
335
 
342
336
  cyberia-client-forest:
343
- image: ${CYBERIA_CLIENT_IMAGE:-underpost/cyberia-client-dev}:${CYBERIA_CLIENT_TAG:-v3.2.90}
337
+ image: ${CYBERIA_CLIENT_IMAGE:-underpost/cyberia-client-dev}:${CYBERIA_CLIENT_TAG:-v3.3.73}
344
338
  container_name: dd-cyberia-client-forest
345
339
  environment:
346
340
  CYBERIA_PORT: '8081'
@@ -365,7 +359,7 @@ services:
365
359
  restart: unless-stopped
366
360
 
367
361
  cyberia-client-test:
368
- image: ${CYBERIA_CLIENT_IMAGE:-underpost/cyberia-client-dev}:${CYBERIA_CLIENT_TAG:-v3.2.90}
362
+ image: ${CYBERIA_CLIENT_IMAGE:-underpost/cyberia-client-dev}:${CYBERIA_CLIENT_TAG:-v3.3.73}
369
363
  container_name: dd-cyberia-client-test
370
364
  environment:
371
365
  CYBERIA_PORT: '8081'
@@ -12,18 +12,19 @@ import swaggerUi from 'swagger-ui-express';
12
12
  import compression from 'compression';
13
13
  import { createServer } from 'http';
14
14
 
15
- import { loggerFactory, loggerMiddleware } from '../../server/logger.js';
15
+ import { loggerFactory, loggerMiddleware } from '../../server/ops/logger.js';
16
16
  import { getCapVariableName, newInstance } from '../../client/components/core/CommonJs.js';
17
17
  import { MailerProvider } from '../../mailer/MailerProvider.js';
18
18
  import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
19
- import { createPeerServer } from '../../server/peer.js';
20
- import { createValkeyConnection } from '../../server/valkey.js';
21
- import { applySecurity, authMiddlewareFactory } from '../../server/auth.js';
19
+ import { createPeerServer } from '../../server/network/peer.js';
20
+ import { createValkeyConnection } from '../../db/valkey/Valkey.js';
21
+ import { applySecurity, authMiddlewareFactory } from '../../server/security/auth.js';
22
22
  import { ssrMiddlewareFactory } from '../../client-builder/ssr.js';
23
23
  import { buildSwaggerUiOptions } from '../../client-builder/client-build-docs.js';
24
24
 
25
- import { shellExec } from '../../server/process.js';
26
- import { devProxyHostFactory, isDevProxyContext, isTlsDevProxy } from '../../server/conf.js';
25
+ import { shellExec } from '../../server/runtime/process.js';
26
+ import { devProxyHostFactory, isDevProxyContext, isTlsDevProxy } from '../../server/runtime/conf.js';
27
+ import { metricsPathFactory } from '../../server/ops/monitoring.js';
27
28
 
28
29
  import Underpost from '../../index.js';
29
30
 
@@ -113,8 +114,9 @@ class ExpressService {
113
114
  return next();
114
115
  });
115
116
 
116
- // Metrics endpoint
117
- app.get(`${path === '/' ? '' : path}/metrics`, async (req, res) => {
117
+ // Metrics endpoint. The route is shared with the Prometheus scrape config
118
+ // so a target can never point at a path this server does not serve.
119
+ app.get(metricsPathFactory(path), async (req, res) => {
118
120
  res.set('Content-Type', promRegister.contentType);
119
121
  return res.end(await promRegister.metrics());
120
122
  });
@@ -163,19 +165,22 @@ class ExpressService {
163
165
  // Create HTTP server for regular instances (required for WebSockets)
164
166
  const server = createServer({}, app);
165
167
 
166
- if (!apiBaseHost) {
167
- // Swagger path definition
168
- const swaggerJsonPath = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
169
- const swaggerPath = `${path === '/' ? `/api-docs` : `${path}/api-docs`}`;
170
-
171
- // Flag swagger requests before security middleware
172
- if (fs.existsSync(swaggerJsonPath)) {
173
- app.use(swaggerPath, (req, res, next) => {
174
- res.locals.isSwagger = true;
175
- next();
176
- });
177
- }
168
+ // Swagger path definition. The UI is served by every instance that renders the
169
+ // client, so a split client/API deployment keeps `api-docs` same-origin with the
170
+ // page that frames it.
171
+ const swaggerJsonPath = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
172
+ const swaggerPath = `${path === '/' ? `/api-docs` : `${path}/api-docs`}`;
173
+ const swaggerEnabled = fs.existsSync(swaggerJsonPath);
174
+
175
+ // Flag swagger requests before security middleware
176
+ if (swaggerEnabled) {
177
+ app.use(swaggerPath, (req, res, next) => {
178
+ res.locals.isSwagger = true;
179
+ next();
180
+ });
181
+ }
178
182
 
183
+ if (!apiBaseHost) {
179
184
  // Security and CORS — must run before swagger-ui so CSP headers are included in swagger responses
180
185
  if (process.env.NODE_ENV === 'development' && useLocalSsl)
181
186
  origins = origins.map((origin) => origin.replace('http', 'https'));
@@ -184,13 +189,6 @@ class ExpressService {
184
189
  origin: origins,
185
190
  });
186
191
 
187
- // Swagger UI setup (after security middleware so responses carry correct CSP headers)
188
- if (fs.existsSync(swaggerJsonPath)) {
189
- const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
190
- const swaggerUiOptions = await buildSwaggerUiOptions();
191
- app.use(swaggerPath, swaggerUi.serve, swaggerUi.setup(swaggerDoc, swaggerUiOptions));
192
- }
193
-
194
192
  // Database and Valkey connections
195
193
  if (db && apis) await DataBaseProviderService.load({ apis, host, path, db });
196
194
 
@@ -261,6 +259,13 @@ class ExpressService {
261
259
  }
262
260
  }
263
261
 
262
+ // Swagger UI setup (after security middleware so responses carry correct CSP headers)
263
+ if (swaggerEnabled) {
264
+ const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
265
+ const swaggerUiOptions = await buildSwaggerUiOptions();
266
+ app.use(swaggerPath, swaggerUi.serve, swaggerUi.setup(swaggerDoc, swaggerUiOptions));
267
+ }
268
+
264
269
  // SSR middleware loading
265
270
  const ssr = await ssrMiddlewareFactory({ app, directory, rootHostPath, path });
266
271
  for (const [_, ssrMiddleware] of Object.entries(ssr)) app.use(ssrMiddleware);
@@ -6,8 +6,9 @@
6
6
  */
7
7
 
8
8
  import fs from 'fs-extra';
9
- import { getRootDirectory, shellCd, shellExec } from '../../server/process.js';
10
- import { loggerFactory } from '../../server/logger.js';
9
+ import { getRootDirectory, shellCd, shellExec } from '../../server/runtime/process.js';
10
+ import { loggerFactory } from '../../server/ops/logger.js';
11
+ import Underpost from '../../index.js';
11
12
 
12
13
  const logger = loggerFactory(import.meta);
13
14
 
@@ -71,12 +72,8 @@ class LamppService {
71
72
  * @memberof LamppService
72
73
  */
73
74
  async initService(options = { daemon: false }) {
74
- let cmd;
75
-
76
- // 1. Write the current virtual host router configuration
77
75
  fs.writeFileSync(`/opt/lampp/etc/extra/httpd-vhosts.conf`, this.router || '', 'utf8');
78
76
 
79
- // 2. Ensure the vhosts file is included in the main httpd.conf
80
77
  const httpdConfPath = `/opt/lampp/etc/httpd.conf`;
81
78
  fs.writeFileSync(
82
79
  httpdConfPath,
@@ -86,12 +83,9 @@ class LamppService {
86
83
  'utf8',
87
84
  );
88
85
 
89
- // 3. Stop the service before making port changes
90
- cmd = `sudo /opt/lampp/lampp stop`;
91
- shellExec(cmd);
86
+ shellExec(`sudo /opt/lampp/lampp stop`);
92
87
 
93
- // 4. Comment out default port Listen directives (80 and 443) to prevent conflicts
94
- // Modify httpd.conf (port 80)
88
+ // Every vhost declares its own Listen, so the stock 80/443 directives would double-bind.
95
89
  if (!fs.readFileSync(httpdConfPath, 'utf8').match(/# Listen 80/))
96
90
  fs.writeFileSync(
97
91
  httpdConfPath,
@@ -99,7 +93,6 @@ class LamppService {
99
93
  'utf8',
100
94
  );
101
95
 
102
- // Modify httpd-ssl.conf (port 443)
103
96
  const httpdSslConfPath = `/opt/lampp/etc/extra/httpd-ssl.conf`;
104
97
  if (fs.existsSync(httpdSslConfPath) && !fs.readFileSync(httpdSslConfPath, 'utf8').match(/# Listen 443/))
105
98
  fs.writeFileSync(
@@ -108,7 +101,8 @@ class LamppService {
108
101
  'utf8',
109
102
  );
110
103
 
111
- // 5. Modify the lampp startup script to bypass port checking for 80 and 443
104
+ // The startup script aborts when 80/443 are already held by the ingress proxy; short-circuit
105
+ // its probes so the service still comes up behind one.
112
106
  const lamppScriptPath = `/opt/lampp/lampp`;
113
107
  if (!fs.readFileSync(lamppScriptPath, 'utf8').match(/testport 443 && false/))
114
108
  fs.writeFileSync(
@@ -123,9 +117,7 @@ class LamppService {
123
117
  'utf8',
124
118
  );
125
119
 
126
- // 6. Start the service
127
- cmd = `sudo /opt/lampp/lampp start`;
128
- shellExec(cmd);
120
+ shellExec(`sudo /opt/lampp/lampp start`);
129
121
  }
130
122
 
131
123
  /**
@@ -217,13 +209,15 @@ class LamppService {
217
209
  * @param {string} options.path - The base path for error documents (e.g., '/app').
218
210
  * @param {string} [options.directory] - Optional absolute path to the document root.
219
211
  * @param {string} [options.rootHostPath] - Relative path from the root directory to the document root, used if `directory` is not provided.
212
+ * @param {string} [options.repository] - Repository backing the document root. Each conf route
213
+ * declares its own, so one host serves as many repositories as it has routes.
220
214
  * @param {boolean} [options.redirect] - If true, enables RewriteEngine for redirection.
221
215
  * @param {string} [options.redirectTarget] - The target URL for redirection.
222
216
  * @param {boolean} [options.resetRouter] - If true, clears the existing router configuration before appending the new one.
223
217
  * @returns {{disabled: boolean}} An object indicating if the service is disabled.
224
218
  * @memberof LamppService
225
219
  */
226
- createApp({ port, host, path, directory, rootHostPath, redirect, redirectTarget, resetRouter }) {
220
+ createApp({ port, host, path, directory, rootHostPath, repository, redirect, redirectTarget, resetRouter }) {
227
221
  if (!this.enabled()) return { disabled: true };
228
222
 
229
223
  if (!this.ports.includes(port)) this.ports.push(port);
@@ -231,7 +225,17 @@ class LamppService {
231
225
 
232
226
  const documentRoot = directory ? directory : `${getRootDirectory()}${rootHostPath}`;
233
227
 
234
- // Append the new VirtualHost configuration
228
+ if (repository) {
229
+ const { accessible } = Underpost.repo.provisionSiteRoot({ host, siteRoot: documentRoot, repository });
230
+ // The checkout keeps its `.git` so the backup pipeline can commit and push it back; the
231
+ // vhost below denies it over HTTP.
232
+ if (accessible) Underpost.repo.initLocalRepo({ path: documentRoot, origin: repository });
233
+ // The vhost is still emitted, so the host answers rather than vanishing from the router —
234
+ // but Apache cannot stat a DocumentRoot that was never created and turns every request into
235
+ // a blanket 403. Named here, because that 403 carries nothing pointing back at this step.
236
+ else logger.error(`${host}: ${documentRoot} not provisioned — this vhost will answer 403 until it is`);
237
+ }
238
+
235
239
  this.appendRouter(`
236
240
  Listen ${port}
237
241
 
@@ -305,55 +309,3 @@ Listen ${port}
305
309
  const Lampp = new LamppService();
306
310
 
307
311
  export { Lampp };
308
-
309
- // -- helper info --
310
-
311
- // ERR too many redirects:
312
- // Check: SELECT * FROM database.wp_options where option_name = 'siteurl' or option_name = 'home';
313
- // Check: wp-config.php
314
- // if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
315
- // $_SERVER['HTTPS'] = 'on';
316
- // }
317
- // For plugins:
318
- // define( 'FS_METHOD', 'direct' );
319
-
320
- // ErrorDocument 404 /custom_404.html
321
- // ErrorDocument 500 /custom_50x.html
322
- // ErrorDocument 502 /custom_50x.html
323
- // ErrorDocument 503 /custom_50x.html
324
- // ErrorDocument 504 /custom_50x.html
325
-
326
- // Respond When Error Pages are Directly Requested
327
-
328
- // <Files "custom_404.html">
329
- // <If "-z %{ENV:REDIRECT_STATUS}">
330
- // RedirectMatch 404 ^/custom_404.html$
331
- // </If>
332
- // </Files>
333
-
334
- // <Files "custom_50x.html">
335
- // <If "-z %{ENV:REDIRECT_STATUS}">
336
- // RedirectMatch 404 ^/custom_50x.html$
337
- // </If>
338
- // </Files>
339
-
340
- // Add www or https with htaccess rewrite
341
-
342
- // Options +FollowSymLinks
343
- // RewriteEngine On
344
- // RewriteCond %{HTTP_HOST} ^example.com [NC]
345
- // RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
346
-
347
- // Redirect http to https with htaccess rewrite
348
-
349
- // RewriteEngine On
350
- // RewriteCond %{SERVER_PORT} 80
351
- // RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]
352
-
353
- // Redirect to HTTPS with www subdomain
354
-
355
- // RewriteEngine On
356
- // RewriteCond %{HTTPS} off [OR]
357
- // RewriteCond %{HTTP_HOST} ^www\. [NC]
358
- // RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
359
- // RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
@@ -9,7 +9,7 @@
9
9
 
10
10
  import fs from 'fs-extra';
11
11
  import path from 'path';
12
- import { loggerFactory } from '../../server/logger.js';
12
+ import { loggerFactory } from '../../server/ops/logger.js';
13
13
 
14
14
  const logger = loggerFactory(import.meta);
15
15
 
@@ -13,8 +13,8 @@
13
13
 
14
14
  import fs from 'fs-extra';
15
15
  import path from 'path';
16
- import { shellExec } from '../../server/process.js';
17
- import { loggerFactory } from '../../server/logger.js';
16
+ import { shellExec } from '../../server/runtime/process.js';
17
+ import { loggerFactory } from '../../server/ops/logger.js';
18
18
  import { Lampp } from '../lampp/Lampp.js';
19
19
  import Underpost from '../../index.js';
20
20
 
@@ -141,14 +141,7 @@ class WpService {
141
141
  ({ freshInstall } = WpService.provisionFresh({ host, siteRoot: wpDir, db, wp, subDir }));
142
142
  }
143
143
 
144
- // Ensure git is initialized and linked to the backup repository.
145
- // Mark the directory as safe before git operations — the site root is owned
146
- // by daemon:daemon (Apache) and git 2.35+ refuses to run in directories owned
147
- // by a different user unless explicitly declared safe.
148
- if (repository) {
149
- shellExec(`git config --global --add safe.directory "${wpDir}"`);
150
- Underpost.repo.initLocalRepo({ path: wpDir, origin: repository });
151
- }
144
+ if (repository) Underpost.repo.initLocalRepo({ path: wpDir, origin: repository });
152
145
 
153
146
  // Write a root .htaccess that rewrites / → /subDir/ when running in subdirectory mode
154
147
  if (subDir) {
@@ -187,9 +180,9 @@ class WpService {
187
180
  }
188
181
 
189
182
  /**
190
- * Clone mode — clones `repository` into `siteRoot` if not present, then
191
- * verifies `wp-config.php` exists. If it is missing the site root is wiped
192
- * and a fresh WordPress install is performed (requires `db` config).
183
+ * Clone mode — materializes `siteRoot` from `repository` via
184
+ * {@link UnderpostRepository.provisionSiteRoot}, then verifies `wp-config.php` exists.
185
+ * An unreachable remote or a checkout without `wp-config.php` falls back to a fresh install.
193
186
  * @param {object} opts
194
187
  * @param {string} opts.host - Virtual-host name (for logging).
195
188
  * @param {string} opts.siteRoot - Absolute path where the site should live.
@@ -197,37 +190,11 @@ class WpService {
197
190
  * @param {object|null} [opts.db] - MariaDB config used as fallback for fresh install.
198
191
  */
199
192
  static provisionClone({ host, siteRoot, repository, db, wp, subDir = '' }) {
200
- if (!process.env.GITHUB_TOKEN && repository && repository.startsWith('https://github.com/')) {
201
- logger.warn(`${host}: GITHUB_TOKEN not set git operations will fail for private repositories`);
202
- }
203
-
204
- // Step 0 — verify the remote repository is reachable; fall back to fresh install if not.
205
- // repository.js isRemoteRepo handles token injection internally.
206
- const repoAccessible = Underpost.repo.isRemoteRepo(repository);
207
- logger.info(`${host}: remote accessible = ${repoAccessible} (${repository})`);
208
- if (!repoAccessible) {
209
- logger.warn(`${host}: remote repository not accessible (${repository}) — running fresh install`);
210
- return WpService.provisionFresh({ host, siteRoot, db, wp, subDir });
211
- }
193
+ const { accessible } = Underpost.repo.provisionSiteRoot({ host, siteRoot, repository });
194
+ if (!accessible) return WpService.provisionFresh({ host, siteRoot, db, wp, subDir });
212
195
 
213
- // Step 1 clone if the directory does not exist yet
214
- if (!fs.existsSync(siteRoot)) {
215
- logger.info(`${host}: cloning ${repository} → ${siteRoot}`);
216
- const cloneUrl = Underpost.repo.resolveAuthUrl(repository);
217
- const tmp = `${siteRoot}.tmp`;
218
- if (fs.existsSync(tmp)) shellExec(`sudo rm -rf "${tmp}"`);
219
- shellExec(`git clone "${cloneUrl}" "${tmp}"`);
220
- shellExec(`sudo mv "${tmp}" "${siteRoot}"`);
221
- shellExec(`sudo chmod -R 755 "${siteRoot}"`);
222
- shellExec(`sudo chown -R daemon:daemon "${siteRoot}"`);
223
- } else {
224
- logger.info(`${host}: repo already present at ${siteRoot}`);
225
- }
226
-
227
- // Step 2 — verify wp-config.php; if missing, wipe and do a fresh install.
228
- // initLocalRepo is NOT called here — createApp always calls it after provisionClone
229
- // returns (whether clone or fallback path) so we avoid a double-init and ensure
230
- // safe.directory is declared before git runs.
196
+ // A checkout without wp-config.php is not a WordPress site: discard it and install fresh.
197
+ // initLocalRepo is left to createApp so both provisioning paths converge on one call.
231
198
  if (!fs.existsSync(path.join(siteRoot, 'wp-config.php'))) {
232
199
  logger.warn(`${host}: wp-config.php not found — wiping site root and running fresh install`);
233
200
  shellExec(`sudo rm -rf "${siteRoot}"`);
@@ -515,10 +482,9 @@ Thumbs.db
515
482
  const repoName = repository.split('/').pop().split('.')[0];
516
483
 
517
484
  logger.info(`${host}: persisting site to repository`);
518
- shellExec(
519
- `cd "${siteRoot}" && git add -A && git commit -m "wp provision ${host} $(date -u +%Y-%m-%dT%H:%M:%SZ)"`,
520
- { silentOnError: true },
521
- );
485
+ shellExec(`cd "${siteRoot}" && git add -A && git commit -m "wp provision ${host} $(date -u +%Y-%m-%dT%H:%M:%SZ)"`, {
486
+ silentOnError: true,
487
+ });
522
488
  shellExec(`cd "${siteRoot}" && underpost push . ${githubOrg}/${repoName} -f`);
523
489
  logger.info(`${host}: initial commit pushed to ${githubOrg}/${repoName}`);
524
490
  }
@@ -630,7 +596,9 @@ if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROT
630
596
 
631
597
  // MariaDB export is handled by the shared db.js backup flow — no duplicate dump here.
632
598
  if (fs.existsSync(path.join(siteRoot, '.git'))) {
633
- shellExec(`cd "${siteRoot}" && git add -A && git commit -m "wp backup $(date -u +%Y-%m-%dT%H:%M:%SZ)"`, { silentOnError: true });
599
+ shellExec(`cd "${siteRoot}" && git add -A && git commit -m "wp backup $(date -u +%Y-%m-%dT%H:%M:%SZ)"`, {
600
+ silentOnError: true,
601
+ });
634
602
  shellExec(`cd "${siteRoot}" && underpost push . ${githubOrg}/${repository.split('/').pop().split('.')[0]}`);
635
603
  logger.info(`backup: git push done for ${siteRoot}`);
636
604
  } else {
@@ -8,9 +8,9 @@
8
8
  * deploy id resolve to the empty catalog — nothing else breaks.
9
9
  *
10
10
  * Each product catalog default-exports the uniform shape documented in
11
- * {@link module:src/server/catalog-cyberia}.
11
+ * {@link module:src/projects/cyberia/catalog-cyberia.js}.
12
12
  *
13
- * @module src/server/catalog.js
13
+ * @module src/server/build/catalog.js
14
14
  * @namespace Catalog
15
15
  */
16
16
 
@@ -18,7 +18,13 @@ import fs from 'fs-extra';
18
18
  import { fileURLToPath } from 'node:url';
19
19
  import * as path from 'node:path';
20
20
 
21
- /** Empty product catalog returned for deploy ids without a dedicated module. */
21
+ /**
22
+ * Empty product catalog returned for deploy ids without a dedicated module.
23
+ *
24
+ * The `package*` fields are the deploy's package manifest contract, read by
25
+ * {@link module:src/server/build/package.js}: a deploy id with no catalog gets the engine
26
+ * manifest under its own identity, and one with a catalog adds exactly what it declares here.
27
+ */
22
28
  const EMPTY_CATALOG = {
23
29
  sourceMoves: [],
24
30
  privateConfPaths: [],
@@ -28,6 +34,10 @@ const EMPTY_CATALOG = {
28
34
  copies: [],
29
35
  keywords: [],
30
36
  description: '',
37
+ packageName: '',
38
+ packageBin: {},
39
+ packageDependencies: {},
40
+ packageScripts: {},
31
41
  };
32
42
 
33
43
  /**
@@ -44,7 +54,7 @@ const loadDeployCatalog = async (deployId) => {
44
54
  const suffix = (deployId ?? '').split('dd-')[1];
45
55
  if (!suffix) return EMPTY_CATALOG;
46
56
  if (fs.existsSync(`./src/projects/${suffix}/catalog-${suffix}.js`)) {
47
- const mod = await import(`../projects/${suffix}/catalog-${suffix}.js`);
57
+ const mod = await import(`../../projects/${suffix}/catalog-${suffix}.js`);
48
58
  return { ...EMPTY_CATALOG, ...(mod.default ?? {}) };
49
59
  }
50
60
  return EMPTY_CATALOG;
@@ -63,7 +73,7 @@ const loadProductCatalogs = async () => {
63
73
  const catalogs = [];
64
74
  for (const file of await fs.readdir('./src/projects')) {
65
75
  if (file === 'underpost') continue;
66
- const mod = await import(`../projects/${file}/catalog-${file}.js`);
76
+ const mod = await import(`../../projects/${file}/catalog-${file}.js`);
67
77
  if (mod.default) catalogs.push({ ...EMPTY_CATALOG, ...mod.default });
68
78
  }
69
79
  return catalogs;