@underpostnet/cyberia 3.3.0 → 3.3.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +17 -5
  3. package/.github/workflows/coverall.cyberia.ci.yml +39 -14
  4. package/.github/workflows/cyberia-client.cd.yml +5 -0
  5. package/.github/workflows/cyberia-server.cd.yml +5 -0
  6. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  7. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  8. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  9. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  10. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  11. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  12. package/.github/workflows/engine-cyberia.cd.yml +3 -0
  13. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  14. package/.github/workflows/ghpkg.ci.yml +35 -20
  15. package/.github/workflows/hardhat.ci.yml +12 -11
  16. package/.github/workflows/npmpkg.ci.yml +17 -15
  17. package/.github/workflows/publish.cyberia.ci.yml +44 -0
  18. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  19. package/.github/workflows/release.cd.yml +1 -0
  20. package/.prettierignore +1 -0
  21. package/AGENTS.md +96 -0
  22. package/CHANGELOG.md +653 -2513
  23. package/CLI-HELP.md +323 -157
  24. package/Dockerfile +25 -9
  25. package/Dockerfile.dev +25 -9
  26. package/Dockerfile.test +5 -5
  27. package/README.md +48 -28
  28. package/bin/build.js +86 -41
  29. package/bin/build.template.js +8 -3
  30. package/bin/cyberia.js +1494 -1403
  31. package/bin/deploy.js +18 -104
  32. package/bin/index.js +1494 -1403
  33. package/compose.env +17 -5
  34. package/conf.js +98 -7
  35. package/deploy/cyberia-client/deploy.sh +46 -0
  36. package/deploy/cyberia-client/package.sh +17 -0
  37. package/deploy/cyberia-client/state.sh +15 -0
  38. package/deploy/cyberia-server/deploy.sh +46 -0
  39. package/deploy/cyberia-server/package.sh +17 -0
  40. package/deploy/cyberia-server/state.sh +15 -0
  41. package/deploy/dd-cyberia/deploy.sh +9 -29
  42. package/deploy/dd-cyberia/init.sh +38 -45
  43. package/deploy/dd-cyberia/package.sh +16 -0
  44. package/deploy/dd-cyberia/state.sh +14 -0
  45. package/deploy/dd-cyberia/sync-deploy.sh +133 -147
  46. package/deploy/lib/config.sh +29 -0
  47. package/deploy/lib/github-actions-logging.sh +610 -0
  48. package/deploy/lib/host.sh +194 -0
  49. package/deploy/lib/state.sh +65 -0
  50. package/deploy/pwa-microservices-template/deploy.sh +17 -42
  51. package/deploy/release/deploy.sh +9 -41
  52. package/deployment.yaml +7 -2
  53. package/docker-compose.yml +23 -17
  54. package/examples/static-page/README.md +19 -19
  55. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  56. package/hardhat/hardhat.config.js +1 -6
  57. package/hardhat/package-lock.json +101 -40
  58. package/hardhat/package.json +2 -2
  59. package/manifests/alertmanager/deployment.yaml +81 -0
  60. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  61. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
  62. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
  63. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  64. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  65. package/manifests/deployment/mongo-express/deployment.yaml +46 -27
  66. package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
  67. package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
  68. package/manifests/deployment/mongo-express/service.yaml +16 -0
  69. package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
  70. package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
  71. package/manifests/grafana/deployment.yaml +26 -7
  72. package/manifests/grafana/kustomization.yaml +1 -0
  73. package/manifests/grafana/service.yaml +6 -1
  74. package/manifests/mariadb/pv.yaml +1 -0
  75. package/manifests/mongodb/statefulset.yaml +9 -2
  76. package/manifests/mysql/pv-pvc.yaml +14 -1
  77. package/manifests/postgresql/pv.yaml +12 -1
  78. package/manifests/postgresql/pvc.yaml +1 -0
  79. package/manifests/prometheus/deployment.yaml +18 -22
  80. package/package.json +87 -12
  81. package/scripts/event-monitor.sh +56 -0
  82. package/scripts/k3s-node-setup.sh +27 -14
  83. package/scripts/kubeadm-node-setup.sh +31 -11
  84. package/scripts/maas-setup.sh +8 -8
  85. package/scripts/selinux-normalize.sh +907 -0
  86. package/scripts/shutdown-machine.sh +843 -0
  87. package/scripts/test-monitor.sh +5 -5
  88. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +15 -10
  89. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
  90. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +7 -2
  91. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +90 -186
  92. package/src/api/core/core.controller.js +1 -1
  93. package/src/api/core/core.router.js +2 -2
  94. package/src/api/core/core.service.js +2 -2
  95. package/src/api/crypto/crypto.controller.js +1 -1
  96. package/src/api/crypto/crypto.service.js +1 -1
  97. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  98. package/src/api/cyberia-action/cyberia-action.router.js +3 -3
  99. package/src/api/cyberia-action/cyberia-action.service.js +5 -6
  100. package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
  101. package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
  102. package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
  103. package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
  104. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +2 -4
  105. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
  106. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +13 -35
  107. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +17 -34
  108. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  109. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
  110. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
  111. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  112. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  113. package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
  114. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  115. package/src/api/cyberia-entity/cyberia-entity.service.js +3 -3
  116. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
  117. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
  118. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -2
  119. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +468 -5
  120. package/src/api/cyberia-instance/cyberia-fallback-capture.js +502 -0
  121. package/src/api/cyberia-instance/cyberia-fallback-world.js +29 -40
  122. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
  123. package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
  124. package/src/api/cyberia-instance/cyberia-instance-map.service.js +35 -142
  125. package/src/api/cyberia-instance/cyberia-instance.controller.js +2 -5
  126. package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
  127. package/src/api/cyberia-instance/cyberia-instance.router.js +5 -18
  128. package/src/api/cyberia-instance/cyberia-instance.service.js +5 -45
  129. package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
  130. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  131. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
  132. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  133. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +76 -3
  134. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  135. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  136. package/src/api/cyberia-map/cyberia-map.service.js +8 -4
  137. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
  138. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
  139. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
  140. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
  141. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  142. package/src/api/cyberia-quest/cyberia-quest.router.js +4 -4
  143. package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
  144. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  145. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
  146. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  147. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  148. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  149. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  150. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  151. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -214
  152. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  153. package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
  154. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  155. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  156. package/src/api/default/default.controller.js +1 -1
  157. package/src/api/default/default.router.js +1 -1
  158. package/src/api/default/default.service.js +2 -2
  159. package/src/api/document/document.controller.js +1 -1
  160. package/src/api/document/document.router.js +1 -1
  161. package/src/api/document/document.service.js +2 -2
  162. package/src/api/file/file.controller.js +1 -1
  163. package/src/api/file/file.ref.js +153 -0
  164. package/src/api/file/file.ref.json +11 -2
  165. package/src/api/file/file.router.js +1 -1
  166. package/src/api/file/file.service.js +2 -2
  167. package/src/api/instance/instance.controller.js +1 -1
  168. package/src/api/instance/instance.router.js +1 -1
  169. package/src/api/instance/instance.service.js +2 -2
  170. package/src/api/ipfs/ipfs.controller.js +1 -1
  171. package/src/api/ipfs/ipfs.router.js +2 -2
  172. package/src/api/ipfs/ipfs.service.js +2 -2
  173. package/src/api/object-layer/object-layer.controller.js +1 -1
  174. package/src/api/object-layer/object-layer.model.js +47 -12
  175. package/src/api/object-layer/object-layer.router.js +12 -5
  176. package/src/api/object-layer/object-layer.service.js +116 -123
  177. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  178. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  179. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  180. package/src/api/test/test.controller.js +1 -1
  181. package/src/api/test/test.service.js +1 -1
  182. package/src/api/user/guest.service.js +3 -3
  183. package/src/api/user/user.controller.js +1 -1
  184. package/src/api/user/user.router.js +2 -2
  185. package/src/api/user/user.service.js +4 -4
  186. package/src/api.js +5 -9
  187. package/src/cli/app.js +402 -0
  188. package/src/cli/baremetal.js +30 -35
  189. package/src/cli/client.js +306 -0
  190. package/src/cli/cloud-init.js +3 -3
  191. package/src/cli/cluster.js +191 -82
  192. package/src/cli/db.js +120 -68
  193. package/src/cli/deploy.js +157 -75
  194. package/src/cli/docker-compose.js +5 -5
  195. package/src/cli/domains.js +184 -0
  196. package/src/cli/dotenv-store.js +143 -0
  197. package/src/cli/event.js +2281 -0
  198. package/src/cli/fs-selection.js +115 -0
  199. package/src/cli/fs.js +159 -343
  200. package/src/cli/host.js +672 -0
  201. package/src/cli/image.js +4 -6
  202. package/src/cli/index.js +343 -151
  203. package/src/cli/ipfs.js +34 -30
  204. package/src/cli/kickstart.js +1 -1
  205. package/src/cli/kubectl.js +218 -41
  206. package/src/cli/lxd.js +3 -3
  207. package/src/cli/monitor.js +1359 -26
  208. package/src/cli/package.js +90 -0
  209. package/src/cli/release.js +16 -12
  210. package/src/cli/repository.js +586 -363
  211. package/src/cli/run.js +398 -843
  212. package/src/cli/secrets.js +2158 -964
  213. package/src/cli/ssh.js +478 -279
  214. package/src/cli/state.js +394 -0
  215. package/src/cli/static.js +2 -2
  216. package/src/cli/system.js +1 -1
  217. package/src/cli/test.js +203 -125
  218. package/src/cli/vultr.js +61 -21
  219. package/src/cli/wireguard.js +1112 -306
  220. package/src/client/components/core/CalendarCore.js +53 -96
  221. package/src/client/components/core/Docs.js +327 -303
  222. package/src/client/components/core/FileExplorer.js +0 -21
  223. package/src/client/components/core/Modal.js +56 -1
  224. package/src/client/components/core/PanelForm.js +4 -4
  225. package/src/client/components/core/Repository.js +56 -0
  226. package/src/client/components/core/Translate.js +7 -0
  227. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  228. package/src/client/components/core/Wallet.js +0 -11
  229. package/src/client/components/core/Worker.js +7 -1
  230. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  231. package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
  232. package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
  233. package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
  234. package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
  235. package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
  236. package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
  237. package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
  238. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
  239. package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
  240. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -35
  241. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
  242. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
  243. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  244. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
  245. package/src/client/components/default/AppShellDefault.js +1 -1
  246. package/src/client/components/default/SettingsDefault.js +2 -2
  247. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  248. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  249. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  250. package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
  251. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +313 -30
  252. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
  253. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
  254. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
  255. package/src/client/public/cyberia-docs/CYBERIA.md +48 -28
  256. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
  257. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  258. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  259. package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
  260. package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
  261. package/src/client/public/default/android-chrome-144x144.png +0 -0
  262. package/src/client/public/default/android-chrome-192x192.png +0 -0
  263. package/src/client/public/default/android-chrome-256x256.png +0 -0
  264. package/src/client/public/default/android-chrome-36x36.png +0 -0
  265. package/src/client/public/default/android-chrome-384x384.png +0 -0
  266. package/src/client/public/default/android-chrome-48x48.png +0 -0
  267. package/src/client/public/default/android-chrome-512x512.png +0 -0
  268. package/src/client/public/default/android-chrome-72x72.png +0 -0
  269. package/src/client/public/default/android-chrome-96x96.png +0 -0
  270. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  271. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  272. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  273. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  274. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  275. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  276. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  277. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  278. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  279. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  280. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  281. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  282. package/src/client/public/default/apple-touch-icon.png +0 -0
  283. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  284. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  285. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  286. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  287. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  288. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  289. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  290. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  291. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  292. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  293. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  294. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  295. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  296. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  297. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  298. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  299. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  300. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  301. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  302. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  303. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  304. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  305. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  306. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  307. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  308. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  309. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  310. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  311. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  312. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  313. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  314. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  315. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  316. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  317. package/src/client/public/default/assets/background/white.jpg +0 -0
  318. package/src/client/public/default/browserconfig.xml +1 -1
  319. package/src/client/public/default/favicon-16x16.png +0 -0
  320. package/src/client/public/default/favicon-32x32.png +0 -0
  321. package/src/client/public/default/favicon-48x48.png +0 -0
  322. package/src/client/public/default/favicon.ico +0 -0
  323. package/src/client/public/default/manifest.webmanifest +5 -5
  324. package/src/client/public/default/mstile-144x144.png +0 -0
  325. package/src/client/public/default/mstile-150x150.png +0 -0
  326. package/src/client/public/default/mstile-310x150.png +0 -0
  327. package/src/client/public/default/mstile-310x310.png +0 -0
  328. package/src/client/public/default/mstile-70x70.png +0 -0
  329. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  330. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  331. package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
  332. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
  333. package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
  334. package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
  335. package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
  336. package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
  337. package/src/client/services/object-layer/object-layer.management.js +6 -10
  338. package/src/client/services/object-layer/object-layer.service.js +3 -1
  339. package/src/client/ssr/RootDocument.js +1 -1
  340. package/src/client/ssr/body/404.js +1 -1
  341. package/src/client/ssr/body/500.js +1 -1
  342. package/src/client/ssr/body/CacheControl.js +1 -1
  343. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  344. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  345. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  346. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  347. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  348. package/src/client/ssr/head/Css.js +1 -1
  349. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  350. package/src/client/ssr/head/DefaultScripts.js +1 -1
  351. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  352. package/src/client/ssr/head/Microdata.js +1 -1
  353. package/src/client/ssr/head/Production.js +1 -1
  354. package/src/client/ssr/head/Pwa.js +1 -1
  355. package/src/client/ssr/head/PwaItemledger.js +1 -1
  356. package/src/client/ssr/head/Seo.js +1 -1
  357. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  358. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  359. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  360. package/src/client/ssr/views/Cyberia404.js +7 -5
  361. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  362. package/src/client/ssr/views/Maintenance.js +1 -1
  363. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  364. package/src/client/ssr/views/Test.js +1 -1
  365. package/src/client/sw/core.sw.js +20 -14
  366. package/src/client-builder/client-build-docs.js +92 -77
  367. package/src/client-builder/client-build-live.js +2 -2
  368. package/src/client-builder/client-build.js +105 -74
  369. package/src/client-builder/client-bundle.js +347 -0
  370. package/src/client-builder/client-dev-server.js +3 -3
  371. package/src/client-builder/client-icons.js +2 -2
  372. package/src/client-builder/ssr.js +3 -3
  373. package/src/client.build.js +3 -6
  374. package/src/client.dev.js +3 -6
  375. package/src/db/DataBaseProvider.js +186 -3
  376. package/src/db/mariadb/MariaDB.js +3 -2
  377. package/src/db/mongo/MongoBootstrap.js +273 -101
  378. package/src/db/mongo/MongoExpress.js +187 -0
  379. package/src/db/mongo/MongooseDB.js +7 -8
  380. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  381. package/src/grpc/cyberia/grpc-server.js +6 -8
  382. package/src/index.js +79 -23
  383. package/src/mailer/EmailRender.js +2 -2
  384. package/src/mailer/MailerInterceptor.js +87 -0
  385. package/src/mailer/MailerProvider.js +50 -6
  386. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +144 -147
  387. package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
  388. package/src/projects/cyberia/besu-genesis-generator.js +8 -17
  389. package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
  390. package/src/projects/cyberia/catalog-cyberia.js +54 -10
  391. package/src/projects/cyberia/gemini-client.js +4 -4
  392. package/src/projects/cyberia/generate-saga.js +5 -12
  393. package/src/projects/cyberia/hot-reload-trigger.js +18 -29
  394. package/src/projects/cyberia/instance-backup.js +210 -0
  395. package/src/projects/cyberia/instance-data.js +178 -258
  396. package/src/projects/cyberia/ipfs-client.js +4 -4
  397. package/src/projects/cyberia/map-preview-generator.js +33 -69
  398. package/src/projects/cyberia/object-layer.js +153 -320
  399. package/src/projects/cyberia/seed-audio.js +139 -0
  400. package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
  401. package/src/projects/cyberia/semantic-layer-generator.js +3 -19
  402. package/src/projects/cyberia/stat-balance.js +81 -0
  403. package/src/projects/cyberia/stat-commands.js +23 -0
  404. package/src/projects/cyberia/stat-contract-generator.js +101 -0
  405. package/src/projects/underpost/catalog-underpost.js +9 -1
  406. package/src/proxy.js +4 -7
  407. package/src/runtime/cyberia-client/Dockerfile +17 -8
  408. package/src/runtime/cyberia-client/Dockerfile.dev +13 -4
  409. package/src/runtime/cyberia-server/Dockerfile +18 -6
  410. package/src/runtime/cyberia-server/Dockerfile.dev +16 -3
  411. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  412. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  413. package/src/runtime/engine-cyberia/Dockerfile.test +5 -5
  414. package/src/runtime/engine-cyberia/compose.env +17 -5
  415. package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
  416. package/src/runtime/express/Express.js +32 -27
  417. package/src/runtime/lampp/Lampp.js +22 -70
  418. package/src/runtime/nginx/Nginx.js +1 -1
  419. package/src/runtime/wp/Wp.js +16 -48
  420. package/src/server/{catalog.js → build/catalog.js} +15 -5
  421. package/src/server/build/coverage.js +188 -0
  422. package/src/server/build/execution.js +402 -0
  423. package/src/server/build/package.js +508 -0
  424. package/src/server/build/testing.js +578 -0
  425. package/src/server/{dns.js → network/dns.js} +144 -11
  426. package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
  427. package/src/server/{middlewares.js → network/middlewares.js} +11 -5
  428. package/src/server/network/node-capability.js +98 -0
  429. package/src/server/{peer.js → network/peer.js} +3 -3
  430. package/src/server/{proxy.js → network/proxy.js} +7 -13
  431. package/src/server/network/router.js +356 -0
  432. package/src/server/{tls.js → network/tls.js} +2 -2
  433. package/src/server/{underpost-compression.js → network/underpost-compression.js} +1 -1
  434. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
  435. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
  436. package/src/server/{cri.js → ops/cri.js} +2 -2
  437. package/src/server/{cron.js → ops/cron.js} +349 -74
  438. package/src/server/ops/event-notification.js +284 -0
  439. package/src/server/{logger.js → ops/logger.js} +143 -23
  440. package/src/server/ops/monitoring.js +1724 -0
  441. package/src/server/{systemd.js → ops/systemd.js} +55 -1
  442. package/src/server/{conf.js → runtime/conf.js} +516 -423
  443. package/src/server/runtime/config-scope.js +215 -0
  444. package/src/server/runtime/environment.js +149 -0
  445. package/src/server/{process.js → runtime/process.js} +153 -12
  446. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  447. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  448. package/src/server/{start.js → runtime/start.js} +128 -39
  449. package/src/server/{auth.js → security/auth.js} +7 -8
  450. package/src/server/security/container-storage.js +382 -0
  451. package/src/server/{crypto.js → security/crypto.js} +1 -1
  452. package/src/server/{selinux.js → security/selinux.js} +1 -1
  453. package/src/server/{backup.js → storage/backup.js} +17 -8
  454. package/src/server/{data-query.js → storage/data-query.js} +17 -1
  455. package/src/server/storage/downloader.js +121 -0
  456. package/src/server/storage/repository.js +68 -0
  457. package/src/server/storage/zip.js +153 -0
  458. package/src/server.js +4 -7
  459. package/src/ws/IoInterface.js +1 -1
  460. package/src/ws/IoServer.js +1 -1
  461. package/src/ws/core/core.ws.connection.js +1 -1
  462. package/src/ws/core/core.ws.emit.js +1 -1
  463. package/src/ws/core/core.ws.server.js +1 -1
  464. package/src/ws/default/default.ws.connection.js +1 -1
  465. package/src/ws/default/default.ws.emit.js +1 -1
  466. package/src/ws/default/default.ws.server.js +1 -1
  467. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  468. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  469. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  470. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  471. package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
  472. package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
  473. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +64 -0
  474. package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
  475. package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
  476. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +17 -23
  477. package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
  478. package/test/integration/app/cyberia/cyberia-load.test.js +466 -0
  479. package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
  480. package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
  481. package/test/integration/app/cyberia/fallback-world-capture.test.js +338 -0
  482. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  483. package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
  484. package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
  485. package/test/integration/app/cyberia/seed-audio.test.js +275 -0
  486. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  487. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  488. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  489. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  490. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  491. package/test/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
  492. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  493. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  494. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  495. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  496. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  497. package/test/integration/infra/2-network/wireguard-cli.test.js +1187 -0
  498. package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +649 -55
  499. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  500. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  501. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  502. package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
  503. package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
  504. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  505. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  506. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  507. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +6 -6
  508. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -4
  509. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  510. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  511. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  512. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  513. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  514. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  515. package/test/support/shell-harness.js +73 -0
  516. package/test/unit/build-template.test.js +97 -0
  517. package/test/unit/build-workflow-offline.test.js +132 -0
  518. package/test/unit/catalog.test.js +71 -0
  519. package/test/unit/client-build-docs.test.js +361 -0
  520. package/test/unit/client-bundle.test.js +313 -0
  521. package/test/unit/conf-loading.test.js +303 -0
  522. package/test/unit/conf-resolution.test.js +996 -0
  523. package/test/unit/coverage-artifact.test.js +221 -0
  524. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  525. package/test/unit/cyberia/instance-backup.test.js +183 -0
  526. package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
  527. package/test/unit/cyberia/publish-workflow.test.js +22 -0
  528. package/test/unit/cyberia/stat-balance.test.js +69 -0
  529. package/test/unit/deploy-env-resolution.test.js +38 -0
  530. package/test/unit/deploy-log-table.test.js +518 -0
  531. package/test/unit/downloader-integrity.test.js +98 -0
  532. package/test/unit/execution-profiles.test.js +219 -0
  533. package/test/unit/file-reference-registry.test.js +141 -0
  534. package/test/unit/fleet-sync-source.test.js +149 -0
  535. package/test/unit/fs-storage-paths.test.js +596 -0
  536. package/test/unit/logger-redaction.test.js +141 -0
  537. package/test/unit/package.test.js +457 -0
  538. package/test/unit/prepare-host.test.js +382 -0
  539. package/test/unit/process-environment.test.js +18 -0
  540. package/test/unit/propagation-message.test.js +78 -0
  541. package/test/unit/redeploy-plan.test.js +24 -0
  542. package/test/unit/release-bump.test.js +474 -0
  543. package/test/unit/ssh-output-redaction.test.js +28 -0
  544. package/test/unit/start-options.test.js +46 -0
  545. package/test/unit/test-tiers.test.js +220 -0
  546. package/test/unit/zip-archive.test.js +142 -0
  547. package/vitest.config.js +66 -0
  548. package/.nycrc +0 -9
  549. package/deploy/lib/logging.sh +0 -96
  550. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  551. package/manifests/mongodb/pv-pvc.yaml +0 -59
  552. package/scripts/coverall-test-cyberia.sh +0 -24
  553. package/scripts/coverall-test.sh +0 -24
  554. package/scripts/link-local-underpost-cli.sh +0 -6
  555. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
  556. package/src/api/user/user.build.js +0 -16
  557. package/src/cli/env.js +0 -177
  558. package/src/client/components/core/Blockchain.js +0 -41
  559. package/src/client/components/core/Blog.js +0 -9
  560. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  561. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
  562. package/src/client/public/default/assets/background/dark.jpg +0 -0
  563. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  564. package/src/client/public/default/assets/background/white0.jpg +0 -0
  565. package/src/client/public/doc/favicon.ico +0 -0
  566. package/src/client/public/doc/sitemap +0 -148
  567. package/src/server/downloader.js +0 -73
  568. package/src/server/environment.js +0 -98
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * Provides a comprehensive set of DNS and IP management utilities,
3
3
  * primarily focused on dynamic DNS (DDNS) updates and network checks.
4
- * @module src/server/dns.js
4
+ * @module src/server/network/dns.js
5
5
  * @namespace UnderpostDns
6
6
  */
7
7
  import axios from 'axios';
8
8
  import validator from 'validator';
9
- import { loggerFactory } from './logger.js';
9
+ import { loggerFactory } from '../ops/logger.js';
10
10
  import dns from 'node:dns';
11
11
  import os from 'node:os';
12
- import { shellExec, pbcopy } from './process.js';
13
- import Underpost from '../index.js';
14
- import { readConfJson } from './conf.js';
12
+ import { shellExec, pbcopy } from '../runtime/process.js';
13
+ import Underpost from '../../index.js';
14
+ import { readConfJson } from '../runtime/conf.js';
15
15
 
16
16
  const logger = loggerFactory(import.meta);
17
17
 
@@ -276,7 +276,50 @@ class Dns {
276
276
  * @static
277
277
  * @memberof UnderpostDns
278
278
  */
279
+ static ensureFilterChains(chains = ['output', 'forward']) {
280
+ // A stock RHEL 9 host with firewalld keeps its rules in `inet firewalld`;
281
+ // there is no `inet filter` table, so every policy command below fails with
282
+ // "No such file or directory". They used to fail silently, which is the
283
+ // worst possible outcome for this subsystem: the caller logged a successful
284
+ // block, the bandwidth guard latched, and the overage it exists to stop
285
+ // kept accruing against a host that was never blocked.
286
+ //
287
+ // Creating our own base chains is additive rather than a firewalld
288
+ // takeover — nftables evaluates every table, so a drop here still wins.
289
+ const ran = (command) => shellExec(command, { silent: true, silentOnError: true })?.code === 0;
290
+ const chainExists = (chain) => ran(`sudo nft list chain inet filter ${chain}`);
291
+ const missing = chains.filter((chain) => !chainExists(chain));
292
+ if (missing.length === 0) return true;
293
+ if (!ran(`sudo nft add table inet filter`)) return false;
294
+ for (const chain of missing) {
295
+ const hook = chain === 'input' ? 'input' : chain;
296
+ if (!ran(`sudo nft add chain inet filter ${chain} '{ type filter hook ${hook} priority 0; policy accept; }'`))
297
+ return false;
298
+ }
299
+ return chains.every(chainExists);
300
+ }
301
+
302
+ /**
303
+ * Whether a chain currently carries the given policy.
304
+ * @static
305
+ * @param {string} chain - Chain name in `inet filter`.
306
+ * @param {string} policy - `accept` or `drop`.
307
+ * @returns {boolean} True when the chain reports that policy.
308
+ * @memberof UnderpostDns
309
+ */
310
+ static chainPolicyIs(chain, policy) {
311
+ const listing = shellExec(`sudo nft list chain inet filter ${chain}`, {
312
+ silent: true,
313
+ stdout: true,
314
+ silentOnError: true,
315
+ });
316
+ return `${listing || ''}`.includes(`policy ${policy}`);
317
+ }
318
+
279
319
  static blockAllEgress() {
320
+ if (!Dns.ensureFilterChains(['output', 'forward']))
321
+ throw new Error('[dns] could not create the inet filter chains; egress is NOT blocked');
322
+
280
323
  // Clear any existing egress rules.
281
324
  shellExec(`sudo nft flush chain inet filter output`, { silent: true });
282
325
  shellExec(`sudo nft flush chain inet filter forward`, { silent: true });
@@ -289,6 +332,12 @@ class Dns {
289
332
  shellExec(`sudo nft chain inet filter output '{ policy drop; }'`, { silent: true });
290
333
  shellExec(`sudo nft chain inet filter forward '{ policy drop; }'`, { silent: true });
291
334
 
335
+ // Read the policy back. The caller latches on this command's exit code, so
336
+ // reporting a block that did not land is what lets an overage run unbounded.
337
+ for (const chain of ['output', 'forward'])
338
+ if (!Dns.chainPolicyIs(chain, 'drop'))
339
+ throw new Error(`[dns] inet filter ${chain} is not 'policy drop'; egress is NOT blocked`);
340
+
292
341
  logger.info('All outbound traffic blocked.');
293
342
  }
294
343
 
@@ -299,6 +348,13 @@ class Dns {
299
348
  * @memberof UnderpostDns
300
349
  */
301
350
  static unblockAllEgress() {
351
+ // Nothing to restore when the chains were never created — that host was
352
+ // never blocked, and saying so beats failing on a missing table.
353
+ if (!Dns.ensureFilterChains(['output', 'forward'])) {
354
+ logger.info('No inet filter chains on this host; egress was never blocked.');
355
+ return;
356
+ }
357
+
302
358
  // Restore default chain policies to accept all traffic.
303
359
  shellExec(`sudo nft chain inet filter output '{ policy accept; }'`, { silent: true });
304
360
  shellExec(`sudo nft chain inet filter forward '{ policy accept; }'`, { silent: true });
@@ -307,9 +363,30 @@ class Dns {
307
363
  shellExec(`sudo nft flush chain inet filter output`, { silent: true });
308
364
  shellExec(`sudo nft flush chain inet filter forward`, { silent: true });
309
365
 
366
+ for (const chain of ['output', 'forward'])
367
+ if (!Dns.chainPolicyIs(chain, 'accept'))
368
+ throw new Error(`[dns] inet filter ${chain} is still not 'policy accept'; egress remains blocked`);
369
+
310
370
  logger.info('All outbound traffic unblocked and restored to default ACCEPT policy.');
311
371
  }
312
372
 
373
+ /**
374
+ * Ensures the chain every ingress rule is installed into exists.
375
+ *
376
+ * `inet filter` can be present with no `input` chain — a firewalld host keeps
377
+ * its rules in `inet firewalld` and never creates one — and every ingress
378
+ * command below then fails on a table that looks like it is there. Creating it
379
+ * with an accept policy and no rules changes nothing by itself.
380
+ * @static
381
+ * @memberof UnderpostDns
382
+ */
383
+ static ensureIngressChain() {
384
+ shellExec(`sudo nft add table inet filter`, { silent: true });
385
+ shellExec(`sudo nft add chain inet filter input '{ type filter hook input priority 0; policy accept; }'`, {
386
+ silent: true,
387
+ });
388
+ }
389
+
313
390
  /**
314
391
  * Blocks all new inbound traffic to this host, except for established/related connections.
315
392
  * This prevents any new incoming connections while keeping existing sessions (like SSH) alive.
@@ -317,6 +394,7 @@ class Dns {
317
394
  * @memberof UnderpostDns
318
395
  */
319
396
  static blockAllIngress() {
397
+ Dns.ensureIngressChain();
320
398
  // Clear any existing ingress rules.
321
399
  shellExec(`sudo nft flush chain inet filter input`, { silent: true });
322
400
 
@@ -330,6 +408,50 @@ class Dns {
330
408
  logger.info('All new inbound traffic blocked.');
331
409
  }
332
410
 
411
+ /**
412
+ * Blocks new inbound traffic to specific TCP ports, leaving every other port
413
+ * reachable.
414
+ *
415
+ * Unlike {@link UnderpostDns.blockAllIngress}, the management path survives:
416
+ * blocking the public edge ports takes published services down while the host
417
+ * can still be reached to put them back. That is the only form of induced
418
+ * ingress outage a remote operator can recover from.
419
+ * @static
420
+ * @param {string} ports - Comma-separated TCP ports.
421
+ * @memberof UnderpostDns
422
+ */
423
+ static blockIngressPort(ports) {
424
+ Dns.ensureIngressChain();
425
+ for (const port of Dns.portListFactory(ports))
426
+ shellExec(`sudo nft insert rule inet filter input tcp dport ${port} counter drop`, { silent: true });
427
+ logger.info('Inbound traffic blocked on ports', { ports: Dns.portListFactory(ports) });
428
+ }
429
+
430
+ /**
431
+ * Withdraws the port rules {@link UnderpostDns.blockIngressPort} installed.
432
+ * @static
433
+ * @param {string} ports - Comma-separated TCP ports.
434
+ * @memberof UnderpostDns
435
+ */
436
+ static unblockIngressPort(ports) {
437
+ Dns.ensureIngressChain();
438
+ for (const port of Dns.portListFactory(ports))
439
+ shellExec(
440
+ `sudo sh -c "nft -a list chain inet filter input | awk '/tcp dport ${port} .*drop/ {print \\$NF}' | ` +
441
+ `xargs -r -n1 nft delete rule inet filter input handle"`,
442
+ { silent: true },
443
+ );
444
+ logger.info('Inbound traffic unblocked on ports', { ports: Dns.portListFactory(ports) });
445
+ }
446
+
447
+ /** Parses a comma-separated port list, keeping only valid TCP ports. */
448
+ static portListFactory(ports = '') {
449
+ return `${ports || ''}`
450
+ .split(',')
451
+ .map((port) => Number(`${port}`.trim()))
452
+ .filter((port) => Number.isInteger(port) && port > 0 && port <= 65535);
453
+ }
454
+
333
455
  /**
334
456
  * Unblocks all inbound traffic to this host.
335
457
  * Restores default input chain policy to ACCEPT and clears ingress rules.
@@ -337,6 +459,7 @@ class Dns {
337
459
  * @memberof UnderpostDns
338
460
  */
339
461
  static unblockAllIngress() {
462
+ Dns.ensureIngressChain();
340
463
  // Restore default chain policy to accept all incoming traffic.
341
464
  shellExec(`sudo nft chain inet filter input '{ policy accept; }'`, { silent: true });
342
465
 
@@ -354,7 +477,7 @@ class Dns {
354
477
  * @memberof UnderpostDns
355
478
  * @param {string} deployList Comma-separated string of deployment IDs to process.
356
479
  * @returns {Promise<void>}
357
- */
480
+ */
358
481
  static async callback(deployList) {
359
482
  const isOnline = await Dns.isInternetConnection();
360
483
 
@@ -368,11 +491,11 @@ class Dns {
368
491
  logger.error(error, { testIp, stack: error.stack });
369
492
  }
370
493
 
371
- const currentIp = Underpost.env.get('ip');
494
+ const currentIp = Underpost.host.store.get('ip');
372
495
 
373
- if (validator.isIP(testIp) && currentIp !== testIp) {
496
+ if (testIp && validator.isIP(testIp) && currentIp !== testIp) {
374
497
  logger.info(`New IP detected`, testIp);
375
- Underpost.env.set('monitor-input', 'pause');
498
+ Underpost.host.store.set('monitor-input', 'pause');
376
499
 
377
500
  for (const _deployId of deployList.split(',')) {
378
501
  const deployId = _deployId.trim();
@@ -415,8 +538,8 @@ class Dns {
415
538
  logger.info(ipUrlTest + ' verify ip', verifyIp);
416
539
  if (verifyIp === testIp) {
417
540
  logger.info('IP updated successfully and verified', testIp);
418
- Underpost.env.set('ip', testIp);
419
- Underpost.env.delete('monitor-input');
541
+ Underpost.host.store.set('ip', testIp);
542
+ Underpost.host.store.delete('monitor-input');
420
543
  } else {
421
544
  logger.error('IP not updated or verification failed', { expected: testIp, received: verifyIp });
422
545
  }
@@ -517,6 +640,8 @@ class Dns {
517
640
  * @property {boolean} [options.unblockAllEgress=false] - Unblock all outbound traffic.
518
641
  * @property {boolean} [options.blockAllIngress=false] - Block all new inbound traffic to this host.
519
642
  * @property {boolean} [options.unblockAllIngress=false] - Unblock all inbound traffic.
643
+ * @property {string} [options.blockIngressPort=''] - Comma-separated TCP ports to block inbound.
644
+ * @property {string} [options.unblockIngressPort=''] - Comma-separated TCP ports to unblock inbound.
520
645
  * @property {boolean} [options.dhcp=false] - Get local DHCP IP instead of public IP.
521
646
  * @property {boolean} [options.copy=false] - Copy the public IP to clipboard.
522
647
  * @return {Promise<string|void>} The public IP if no ban/unban action is taken.
@@ -538,6 +663,8 @@ class Dns {
538
663
  unblockAllEgress: false,
539
664
  blockAllIngress: false,
540
665
  unblockAllIngress: false,
666
+ blockIngressPort: '',
667
+ unblockIngressPort: '',
541
668
  copy: false,
542
669
  dhcp: false,
543
670
  },
@@ -594,6 +721,12 @@ class Dns {
594
721
  if (options.unblockAllEgress) {
595
722
  return Dns.unblockAllEgress();
596
723
  }
724
+ if (options.blockIngressPort) {
725
+ return Dns.blockIngressPort(options.blockIngressPort);
726
+ }
727
+ if (options.unblockIngressPort) {
728
+ return Dns.unblockIngressPort(options.unblockIngressPort);
729
+ }
597
730
  if (options.blockAllIngress) {
598
731
  return Dns.blockAllIngress();
599
732
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Authenticated HTTP/HTTPS forward-proxy primitives.
3
- * @module src/server/forward-proxy.js
3
+ * @module src/server/network/forward-proxy.js
4
4
  * @namespace ForwardProxy
5
5
  */
6
6
  'use strict';
@@ -9,14 +9,15 @@ import http from 'node:http';
9
9
  import https from 'node:https';
10
10
  import net from 'node:net';
11
11
  import os from 'node:os';
12
- import { environmentValueFactory } from './environment.js';
13
- import { loggerFactory, loggerMiddleware } from './logger.js';
12
+ import { environmentValueFactory } from '../runtime/environment.js';
13
+ import { loggerFactory, loggerMiddleware } from '../ops/logger.js';
14
14
  import {
15
- homeDirectoryPathFactory,
16
- systemdRunCommandFactory,
15
+ nodeCandidatesFactory,
16
+ nodeProbeCommandFactory,
17
+ scriptProbeCommandFactory,
17
18
  systemdServiceCommandsFactory,
18
19
  systemdUnitFactory,
19
- } from './systemd.js';
20
+ } from '../ops/systemd.js';
20
21
 
21
22
  const logger = loggerFactory(import.meta);
22
23
  const proxyLogger = loggerFactory(import.meta, 'debug');
@@ -181,11 +182,7 @@ const forwardProxyCommandFactory = ({ host, port, execPath = process.execPath, s
181
182
  const forwardProxyNodeCandidatesFactory = ({
182
183
  execPath = process.execPath,
183
184
  systemPaths = FORWARD_PROXY.nodePaths,
184
- } = {}) => {
185
- const own = `${execPath || ''}`.trim();
186
- const inHome = homeDirectoryPathFactory(own);
187
- return [...new Set([...(own && !inHome ? [own] : []), ...systemPaths, ...(own && inHome ? [own] : [])])];
188
- };
185
+ } = {}) => nodeCandidatesFactory({ execPath, systemPaths });
189
186
 
190
187
  /**
191
188
  * Builds a transient systemd command that probes a Node executable.
@@ -196,7 +193,7 @@ const forwardProxyNodeCandidatesFactory = ({
196
193
  * @memberof ForwardProxy
197
194
  */
198
195
  const forwardProxyNodeProbeCommandFactory = (nodePath, user = os.userInfo().username) =>
199
- systemdRunCommandFactory({ command: `${nodePath} --version`, user, properties: { Type: 'oneshot' } });
196
+ nodeProbeCommandFactory(nodePath, user);
200
197
 
201
198
  /**
202
199
  * Builds a transient systemd command that probes the proxy entry script.
@@ -210,12 +207,7 @@ const forwardProxyStartProbeCommandFactory = ({
210
207
  scriptPath = process.argv[1],
211
208
  user = os.userInfo().username,
212
209
  workingDirectory = process.cwd(),
213
- }) =>
214
- systemdRunCommandFactory({
215
- command: `${nodePath} ${scriptPath} --version`,
216
- user,
217
- properties: { Type: 'oneshot', WorkingDirectory: workingDirectory },
218
- });
210
+ }) => scriptProbeCommandFactory({ nodePath, scriptPath, user, workingDirectory });
219
211
 
220
212
  /**
221
213
  * Renders the systemd unit used to supervise the forward proxy.
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Express middleware and controller/router helpers for engine APIs.
3
3
  *
4
- * @module src/server/middlewares.js
4
+ * @module src/server/network/middlewares.js
5
5
  * @namespace Middlewares
6
6
  */
7
7
 
8
- import { loggerFactory } from './logger.js';
9
- import { moderatorGuard, adminGuard } from './auth.js';
8
+ import { loggerFactory } from '../ops/logger.js';
9
+ import { moderatorGuard, adminGuard } from '../security/auth.js';
10
10
 
11
11
  const logger = loggerFactory(import.meta);
12
12
 
@@ -152,8 +152,14 @@ const buildCrudController = (service, extend = {}) => {
152
152
  class CrudController {
153
153
  /** @static @memberof Middlewares */
154
154
  static post = serviceHandler(service.post);
155
- /** @static @memberof Middlewares */
156
- static get = serviceHandler(service.get, { pagination: true });
155
+ /**
156
+ * Reads are public and cross-origin by default: the browser client is served from its own
157
+ * origin and every list/read it issues is a plain GET against this API. Without the header
158
+ * the response arrives with status 200 and is then discarded by the same-origin policy,
159
+ * which reads as a silent feature failure rather than a transport error.
160
+ * @static @memberof Middlewares
161
+ */
162
+ static get = serviceHandler(service.get, { pagination: true, crossOrigin: true });
157
163
  /** @static @memberof Middlewares */
158
164
  static put = serviceHandler(service.put);
159
165
  /** @static @memberof Middlewares */
@@ -0,0 +1,98 @@
1
+ /**
2
+ * What each node role is allowed to do, as one table the rest of the platform reads.
3
+ *
4
+ * The roles are the three the topology already defines — `hub`, `control`, `worker` — and this
5
+ * module adds no fourth. What it adds is a single answer to a question that was previously spread
6
+ * across the commands that happened to ask it: `wireguard` knew HAProxy is hub-only, `event` knew
7
+ * the dispatcher is control-only, and the sync steps knew cron publication is control-only, but
8
+ * nothing stated the boundary those three agree on.
9
+ *
10
+ * The distinction the table exists to hold is between a Kubernetes **node** and a Kubernetes
11
+ * **administrator**. A worker runs the kubelet and joins the cluster; that is node runtime, and it
12
+ * is not permission to administer the cluster it belongs to. Being managed by the host domain is
13
+ * not permission either — `underpost host` is node-level operational configuration, and every role
14
+ * has it.
15
+ *
16
+ * @module src/server/network/node-capability.js
17
+ * @namespace NodeCapability
18
+ */
19
+
20
+ /**
21
+ * @constant NODE_CAPABILITIES
22
+ * @description Capabilities held by each role, derived from the operations the repository
23
+ * actually gates: HAProxy and the forward proxy refuse to configure themselves off the hub, the
24
+ * dispatcher refuses to install off a control node, and the sync sequence publishes CronJobs from
25
+ * the control node alone.
26
+ * @memberof NodeCapability
27
+ */
28
+ const NODE_CAPABILITIES = Object.freeze({
29
+ hub: Object.freeze([
30
+ 'host-configuration',
31
+ 'wireguard-hub',
32
+ 'haproxy',
33
+ 'forward-proxy',
34
+ 'edge-routing',
35
+ 'node-metrics',
36
+ ]),
37
+ control: Object.freeze([
38
+ 'host-configuration',
39
+ 'wireguard-spoke',
40
+ 'kubernetes-node',
41
+ 'kubernetes-administration',
42
+ 'cluster-secret-administration',
43
+ 'cron-publication',
44
+ 'event-service',
45
+ 'node-metrics',
46
+ ]),
47
+ worker: Object.freeze(['host-configuration', 'wireguard-spoke', 'kubernetes-node', 'node-metrics']),
48
+ });
49
+
50
+ /** The roles the topology defines. Ordered hub-first, as every fleet listing is. */
51
+ const NODE_ROLES = Object.freeze(Object.keys(NODE_CAPABILITIES));
52
+
53
+ /**
54
+ * Capabilities that reach the Kubernetes API with cluster-wide authority.
55
+ *
56
+ * Named apart from the rest because they are the ones a role must never acquire by side effect:
57
+ * possessing `kubectl`, joining the cluster, or carrying the host environment are each a reason
58
+ * someone might assume these follow, and none of them is.
59
+ * @memberof NodeCapability
60
+ */
61
+ const CLUSTER_ADMIN_CAPABILITIES = Object.freeze([
62
+ 'kubernetes-administration',
63
+ 'cluster-secret-administration',
64
+ 'cron-publication',
65
+ ]);
66
+
67
+ /**
68
+ * Whether a role holds a capability.
69
+ * @param {string} role - `hub`, `control` or `worker`.
70
+ * @param {string} capability - Capability name.
71
+ * @returns {boolean} True when the role holds it.
72
+ * @memberof NodeCapability
73
+ */
74
+ const roleHasCapability = (role, capability) => (NODE_CAPABILITIES[role] || []).includes(capability);
75
+
76
+ /**
77
+ * Refuses an operation the role does not hold the capability for.
78
+ *
79
+ * Fail-closed on an unknown role as well as an unheld capability: a node whose document names a
80
+ * role this table does not define has no capabilities, rather than the union of the ones it might
81
+ * have meant.
82
+ * @param {object} params - Assertion context.
83
+ * @param {string} params.role - Role of the node the operation would run on.
84
+ * @param {string} params.capability - Capability the operation requires.
85
+ * @param {string} params.operation - Operation being attempted, named in the refusal.
86
+ * @throws {Error} When the role does not hold the capability.
87
+ * @memberof NodeCapability
88
+ */
89
+ const assertRoleCapability = ({ role, capability, operation }) => {
90
+ if (roleHasCapability(role, capability)) return;
91
+ const held = NODE_CAPABILITIES[role];
92
+ throw new Error(
93
+ `[capability] ${operation} requires '${capability}', which the '${role || '(unset)'}' role does not hold; ` +
94
+ (held ? `it holds ${held.join(', ')}` : `known roles are ${NODE_ROLES.join(', ')}`),
95
+ );
96
+ };
97
+
98
+ export { CLUSTER_ADMIN_CAPABILITIES, NODE_CAPABILITIES, NODE_ROLES, assertRoleCapability, roleHasCapability };
@@ -3,14 +3,14 @@
3
3
  * Initializes and configures the PeerJS server instance, typically running
4
4
  * alongside a main Node.js application.
5
5
  *
6
- * @module src/server/peer.js
6
+ * @module src/server/network/peer.js
7
7
  * @namespace Peer
8
8
  */
9
9
 
10
10
  import { PeerServer } from 'peer';
11
11
  import dotenv from 'dotenv';
12
- import { loggerFactory } from './logger.js';
13
- import Underpost from '../index.js';
12
+ import { loggerFactory } from '../ops/logger.js';
13
+ import Underpost from '../../index.js';
14
14
 
15
15
  /**
16
16
  * Logger instance for this module, utilizing the framework's factory.
@@ -1,26 +1,20 @@
1
1
  /**
2
2
  * Manages the creation and configuration of the reverse proxy server,
3
3
  * including handling HTTP/HTTPS listeners and routing based on host configuration.
4
- * @module src/server/proxy.js
4
+ * @module src/server/network/proxy.js
5
5
  * @namespace ProxyService
6
6
  */
7
7
  'use strict';
8
8
 
9
9
  import express from 'express';
10
10
  import { createProxyMiddleware } from 'http-proxy-middleware';
11
- import { loggerFactory, loggerMiddleware } from './logger.js';
12
- import {
13
- buildPortProxyRouter,
14
- buildProxyRouter,
15
- etcHostFactory,
16
- getTlsHosts,
17
- isDevProxyContext,
18
- isTlsDevProxy,
19
- } from './conf.js';
20
-
21
- import { shellExec } from './process.js';
11
+ import { loggerFactory, loggerMiddleware } from '../ops/logger.js';
12
+ import { etcHostFactory, getTlsHosts, isDevProxyContext, isTlsDevProxy } from '../runtime/conf.js';
13
+ import { buildPortProxyRouter, buildProxyRouter } from './router.js';
14
+
15
+ import { shellExec } from '../runtime/process.js';
22
16
  import fs from 'fs-extra';
23
- import Underpost from '../index.js';
17
+ import Underpost from '../../index.js';
24
18
 
25
19
  const logger = loggerFactory(import.meta);
26
20