@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
@@ -9,12 +9,13 @@
9
9
  * Out of scope: domain model factories, DTO projection — those belong in
10
10
  * their respective service modules (e.g. guest.service.js).
11
11
  *
12
- * @module src/server/valkey.js
12
+ * @module src/db/valkey/Valkey.js
13
13
  * @namespace ValkeyService
14
14
  */
15
15
  import Valkey from 'iovalkey';
16
- import { loggerFactory } from './logger.js';
17
- import Underpost from '../index.js';
16
+ import { loggerFactory } from '../../server/ops/logger.js';
17
+ import Underpost from '../../index.js';
18
+ import { latchRuntimeError } from '../../server/runtime/runtime-status.js';
18
19
 
19
20
  const logger = loggerFactory(import.meta);
20
21
 
@@ -71,7 +72,7 @@ const createValkeyConnection = async (instance = {}, connectionOptions = {}) =>
71
72
  client.on('error', (err) => {
72
73
  ValkeyStatus[key] = 'error';
73
74
  logger.error('Valkey error', { err: err?.message, instance });
74
- if (Underpost.env.isInsideContainer()) Underpost.env.set('container-status', 'error');
75
+ latchRuntimeError();
75
76
  });
76
77
  client.on('reconnecting', () => {
77
78
  ValkeyStatus[key] = 'reconnecting';
@@ -13,7 +13,7 @@ import * as grpc from '@grpc/grpc-js';
13
13
  import * as protoLoader from '@grpc/proto-loader';
14
14
  import path from 'path';
15
15
  import { fileURLToPath } from 'url';
16
- import { loggerFactory } from '../../server/logger.js';
16
+ import { loggerFactory } from '../../server/ops/logger.js';
17
17
  import {
18
18
  buildFallbackConfig,
19
19
  buildFallbackInstanceConfig,
package/src/index.js CHANGED
@@ -5,33 +5,40 @@
5
5
  */
6
6
 
7
7
  import UnderpostBaremetal from './cli/baremetal.js';
8
+ import UnderpostApp from './cli/app.js';
9
+ import UnderpostClient from './cli/client.js';
10
+ import UnderpostHost from './cli/host.js';
8
11
  import UnderpostCloudInit from './cli/cloud-init.js';
9
12
  import UnderpostKickStart from './cli/kickstart.js';
10
13
  import UnderpostCluster from './cli/cluster.js';
11
14
  import UnderpostDB from './cli/db.js';
12
15
  import UnderpostDeploy from './cli/deploy.js';
13
16
  import UnderpostDockerCompose from './cli/docker-compose.js';
17
+ import UnderpostEvent from './cli/event.js';
14
18
  import UnderpostKubectl from './cli/kubectl.js';
15
- import UnderpostRootEnv from './cli/env.js';
16
19
  import UnderpostFileStorage from './cli/fs.js';
17
20
  import UnderpostIPFS from './cli/ipfs.js';
18
21
  import UnderpostImage from './cli/image.js';
19
22
  import UnderpostLxd from './cli/lxd.js';
20
23
  import UnderpostMonitor from './cli/monitor.js';
24
+ import UnderpostPackage from './cli/package.js';
21
25
  import UnderpostRepository from './cli/repository.js';
22
26
  import UnderpostRun from './cli/run.js';
23
27
  import UnderpostSecret from './cli/secrets.js';
24
28
  import UnderpostSSH from './cli/ssh.js';
29
+ import UnderpostState from './cli/state.js';
25
30
  import UnderpostStatic from './cli/static.js';
26
31
  import UnderpostTest from './cli/test.js';
27
32
  import UnderpostRelease from './cli/release.js';
28
33
  import UnderpostSystemProvisionig from './cli/system.js';
34
+ import UnderpostVultr from './cli/vultr.js';
35
+ import UnderpostWireguard from './cli/wireguard.js';
29
36
 
30
- import UnderpostDns from './server/dns.js';
31
- import UnderpostBackup from './server/backup.js';
32
- import UnderpostCron from './server/cron.js';
33
- import UnderpostStartUp from './server/start.js';
34
- import UnderpostTLS from './server/tls.js';
37
+ import UnderpostDns from './server/network/dns.js';
38
+ import UnderpostBackup from './server/storage/backup.js';
39
+ import UnderpostCron from './server/ops/cron.js';
40
+ import UnderpostStartUp from './server/runtime/start.js';
41
+ import UnderpostTLS from './server/network/tls.js';
35
42
 
36
43
  /**
37
44
  * Underpost main module methods
@@ -45,7 +52,7 @@ class Underpost {
45
52
  * @type {String}
46
53
  * @memberof Underpost
47
54
  */
48
- static version = 'v3.2.90';
55
+ static version = 'v3.3.73';
49
56
 
50
57
  /**
51
58
  * Required Node.js major version
@@ -65,24 +72,14 @@ class Underpost {
65
72
  return UnderpostRepository.API;
66
73
  }
67
74
  /**
68
- * Root Env cli API
75
+ * Client build cli API
69
76
  * @static
70
- * @type {UnderpostRootEnv.API}
77
+ * @type {UnderpostClient.API}
71
78
  * @memberof Underpost
72
79
  */
73
- static get env() {
74
- return UnderpostRootEnv.API;
80
+ static get client() {
81
+ return UnderpostClient.API;
75
82
  }
76
- /**
77
- * Test cli API
78
- * @static
79
- * @type {UnderpostTest.API}
80
- * @memberof Underpost
81
- */
82
- static get test() {
83
- return UnderpostTest.API;
84
- }
85
-
86
83
  /**
87
84
  * Static cli API
88
85
  * @static
@@ -117,6 +114,33 @@ class Underpost {
117
114
  * @type {UnderpostSecret.API}
118
115
  * @memberof Underpost
119
116
  */
117
+ static get host() {
118
+ return UnderpostHost.API;
119
+ }
120
+ /**
121
+ * App deployment environment domain cli API
122
+ * @static
123
+ * @type {UnderpostApp.API}
124
+ * @memberof Underpost
125
+ */
126
+ static get app() {
127
+ return UnderpostApp.API;
128
+ }
129
+ /**
130
+ * Workload secret store domain cli API
131
+ * @static
132
+ * @type {UnderpostSecret.API}
133
+ * @memberof Underpost
134
+ */
135
+ static get state() {
136
+ return UnderpostState.API;
137
+ }
138
+ /**
139
+ * Workload secret store domain cli API
140
+ * @static
141
+ * @type {UnderpostSecret.API}
142
+ * @memberof Underpost
143
+ */
120
144
  static get secret() {
121
145
  return UnderpostSecret.API;
122
146
  }
@@ -183,6 +207,15 @@ class Underpost {
183
207
  static get monitor() {
184
208
  return UnderpostMonitor.API;
185
209
  }
210
+ /**
211
+ * Operational event dispatcher cli API
212
+ * @static
213
+ * @type {UnderpostEvent.API}
214
+ * @memberof Underpost
215
+ */
216
+ static get event() {
217
+ return UnderpostEvent.API;
218
+ }
186
219
  /**
187
220
  * SSH cli API
188
221
  * @static
@@ -252,6 +285,26 @@ class Underpost {
252
285
  return UnderpostSystemProvisionig.API;
253
286
  }
254
287
 
288
+ /**
289
+ * Edge hub WireGuard/HAProxy cli API
290
+ * @static
291
+ * @type {UnderpostWireguard.API}
292
+ * @memberof Underpost
293
+ */
294
+ static get wireguard() {
295
+ return UnderpostWireguard.API;
296
+ }
297
+
298
+ /**
299
+ * Vultr bandwidth guard cli API
300
+ * @static
301
+ * @type {UnderpostVultr.API}
302
+ * @memberof Underpost
303
+ */
304
+ static get vultr() {
305
+ return UnderpostVultr.API;
306
+ }
307
+
255
308
  /**
256
309
  * Dns server API
257
310
  * @static
@@ -311,6 +364,26 @@ class Underpost {
311
364
  static get release() {
312
365
  return UnderpostRelease.API;
313
366
  }
367
+
368
+ /**
369
+ * Test runner cli API
370
+ * @static
371
+ * @type {UnderpostTest.API}
372
+ * @memberof Underpost
373
+ */
374
+ static get test() {
375
+ return UnderpostTest.API;
376
+ }
377
+
378
+ /**
379
+ * Deploy package manifest cli API
380
+ * @static
381
+ * @type {UnderpostPackage.API}
382
+ * @memberof Underpost
383
+ */
384
+ static get package() {
385
+ return UnderpostPackage.API;
386
+ }
314
387
  }
315
388
 
316
389
  if (!process.version || !process.version.startsWith(`${Underpost.majorNodejsVersion}.`))
@@ -332,26 +405,33 @@ export {
332
405
  UnderpostDB,
333
406
  UnderpostDeploy,
334
407
  UnderpostDockerCompose,
408
+ UnderpostEvent,
335
409
  UnderpostKubectl,
336
- UnderpostRootEnv,
337
410
  UnderpostFileStorage,
338
411
  UnderpostImage,
339
412
  UnderpostStatic,
413
+ UnderpostTest,
340
414
  UnderpostLxd,
341
415
  UnderpostKickStart,
342
416
  UnderpostIPFS,
343
417
  UnderpostMonitor,
418
+ UnderpostPackage,
419
+ UnderpostApp,
420
+ UnderpostClient,
421
+ UnderpostHost,
344
422
  UnderpostRepository,
345
423
  UnderpostRun,
346
424
  UnderpostSecret,
347
425
  UnderpostSSH,
348
- UnderpostTest,
426
+ UnderpostState,
349
427
  UnderpostDns,
350
428
  UnderpostBackup,
351
429
  UnderpostCron,
352
430
  UnderpostStartUp,
353
431
  UnderpostRelease,
354
432
  UnderpostTLS,
433
+ UnderpostVultr,
434
+ UnderpostWireguard,
355
435
  };
356
436
 
357
437
  export default Underpost;
@@ -98,8 +98,8 @@ class EmailRenderService {
98
98
  for (const templateKey of Object.keys(options.templates)) {
99
99
  const ssrEmailComponent = options.templates[templateKey];
100
100
  // Note: ssrFactory is assumed to load and return a functional component/function
101
- const SrrComponent = await ssrFactory(`./src/client/ssr/mailer/${ssrEmailComponent}.js`);
102
- templates[templateKey] = SrrComponent(this, options);
101
+ const SSRComponent = await ssrFactory(`./src/client/ssr/mailer/${ssrEmailComponent}.js`);
102
+ templates[templateKey] = SSRComponent(this, options);
103
103
  }
104
104
  return templates;
105
105
  }
@@ -0,0 +1,87 @@
1
+ import { MailerProvider } from './MailerProvider.js';
2
+
3
+ /**
4
+ * General-purpose capture of everything {@link MailerProviderService#send}
5
+ * delivers, built on the provider's send middleware.
6
+ *
7
+ * Assertions about mail are otherwise only possible against a real inbox. The
8
+ * interceptor records the delivery context and the transport result of each
9
+ * send, which is what lets a caller wait for a specific message and know
10
+ * whether the transport actually accepted it.
11
+ *
12
+ * @module src/mailer/MailerInterceptor.js
13
+ * @namespace MailerInterceptor
14
+ */
15
+
16
+ /**
17
+ * @typedef {object} InterceptedMail
18
+ * @property {string} id - Mailer instance the message was sent through.
19
+ * @property {object} sendOptions - Nodemailer options as the transport received them.
20
+ * @property {object|undefined} info - Transport result; `undefined` when delivery failed.
21
+ * @property {boolean} accepted - Whether the transport accepted the message.
22
+ * @property {string} at - ISO timestamp of the delivery attempt.
23
+ * @memberof MailerInterceptor
24
+ */
25
+
26
+ /**
27
+ * @method mailerInterceptorFactory
28
+ * @description Installs a send interceptor and returns its recorder.
29
+ *
30
+ * The interceptor is transparent: it forwards every send to the transport and
31
+ * records the outcome. `suppress` holds the message instead, for callers that
32
+ * must exercise the send path without delivering.
33
+ *
34
+ * @param {object} [params]
35
+ * @param {import('./MailerProvider.js').MailerProvider} [params.provider] - Provider to intercept.
36
+ * @param {function(object): boolean} [params.filter] - Records only the contexts it accepts.
37
+ * @param {boolean} [params.suppress=false] - Record without handing the message to the transport.
38
+ * @returns {{messages: Array<InterceptedMail>, waitFor: function, close: function(): void}} Recorder.
39
+ * @memberof MailerInterceptor
40
+ */
41
+ const mailerInterceptorFactory = ({ provider = MailerProvider, filter, suppress = false } = {}) => {
42
+ const messages = [];
43
+
44
+ const dispose = provider.use(async (context, next) => {
45
+ const matched = !filter || filter(context);
46
+ const info = matched && suppress ? { messageId: `suppressed:${Date.now()}`, suppressed: true } : await next();
47
+ if (matched)
48
+ messages.push({
49
+ id: context.id,
50
+ sendOptions: context.sendOptions,
51
+ info,
52
+ accepted: Boolean(info),
53
+ at: new Date().toISOString(),
54
+ });
55
+ return info;
56
+ });
57
+
58
+ return {
59
+ messages,
60
+
61
+ /**
62
+ * Resolves with the first recorded message matching `predicate`.
63
+ *
64
+ * Polls rather than resolving on registration, because a send started
65
+ * before the caller began waiting must still satisfy the wait.
66
+ *
67
+ * @param {function(InterceptedMail): boolean} predicate - Match to wait for.
68
+ * @param {object} [options]
69
+ * @param {number} [options.timeoutMs=60000] - Maximum wait.
70
+ * @param {number} [options.intervalMs=250] - Poll interval.
71
+ * @returns {Promise<InterceptedMail|undefined>} The match, or `undefined` on timeout.
72
+ */
73
+ async waitFor(predicate, { timeoutMs = 60000, intervalMs = 250 } = {}) {
74
+ const deadline = Date.now() + timeoutMs;
75
+ do {
76
+ const match = messages.find(predicate);
77
+ if (match) return match;
78
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
79
+ } while (Date.now() < deadline);
80
+ return messages.find(predicate);
81
+ },
82
+
83
+ close: dispose,
84
+ };
85
+ };
86
+
87
+ export { mailerInterceptorFactory };
@@ -1,5 +1,5 @@
1
1
  import nodemailer from 'nodemailer';
2
- import { loggerFactory } from '../server/logger.js';
2
+ import { loggerFactory } from '../server/ops/logger.js';
3
3
  import { EmailRender } from './EmailRender.js';
4
4
 
5
5
  /**
@@ -45,6 +45,12 @@ class MailerProviderService {
45
45
  */
46
46
  #instance = {};
47
47
 
48
+ /**
49
+ * Registered send middlewares, in the order they wrap a delivery.
50
+ * @type {Array<function(object, function(): Promise<object|undefined>): Promise<object|undefined>>}
51
+ */
52
+ #middlewares = [];
53
+
48
54
  /**
49
55
  * Retrieves the internal instance storage for direct access (used for backward compatibility).
50
56
  * @returns {object.<string, object>} The internal mailer instance map.
@@ -53,6 +59,28 @@ class MailerProviderService {
53
59
  return this.#instance;
54
60
  }
55
61
 
62
+ /**
63
+ * Registers a send middleware.
64
+ *
65
+ * Middlewares wrap every {@link MailerProviderService#send}, in registration
66
+ * order, and receive the delivery context plus the `next` continuation that
67
+ * yields the transport result. A middleware that never calls `next` suppresses
68
+ * the delivery, which is what makes this usable both for cross-cutting
69
+ * concerns (auditing, rate limiting) and for capturing mail in a test run.
70
+ *
71
+ * @param {function(object, function(): Promise<object|undefined>): Promise<object|undefined>} middleware -
72
+ * Receives `({ id, sendOptions, sender }, next)`.
73
+ * @returns {function(): void} Disposer that unregisters the middleware.
74
+ */
75
+ use(middleware) {
76
+ if (typeof middleware !== 'function') throw new Error('[mailer] a send middleware must be a function');
77
+ this.#middlewares.push(middleware);
78
+ return () => {
79
+ const index = this.#middlewares.indexOf(middleware);
80
+ if (index !== -1) this.#middlewares.splice(index, 1);
81
+ };
82
+ }
83
+
56
84
  /**
57
85
  * Loads and initializes a new mailer provider instance using Nodemailer.
58
86
  * The created instance is stored internally and includes the transporter and rendered templates.
@@ -145,6 +173,24 @@ class MailerProviderService {
145
173
  }
146
174
  }
147
175
 
176
+ /**
177
+ * Closes a loaded instance's transport and forgets it.
178
+ *
179
+ * A transport holds an open socket, which keeps a one-shot process alive long
180
+ * after its work is done. Callers that load an instance for a single delivery
181
+ * release it here; a long-running server keeps its instances loaded instead.
182
+ *
183
+ * @param {string} id - Mailer instance id.
184
+ * @returns {boolean} True when an instance was closed.
185
+ */
186
+ close(id) {
187
+ const instance = this.#instance[id];
188
+ if (!instance) return false;
189
+ if (typeof instance.transporter?.close === 'function') instance.transporter.close();
190
+ delete this.#instance[id];
191
+ return true;
192
+ }
193
+
148
194
  /**
149
195
  * Sends an email using a previously loaded transporter instance.
150
196
  *
@@ -189,12 +235,10 @@ class MailerProviderService {
189
235
 
190
236
  if (!sendOptions.from) sendOptions.from = `${instance.sender.name} <${instance.sender.email}>`;
191
237
 
192
- // send mail with defined transport object
193
- const info = await instance.transporter.sendMail(sendOptions);
194
-
195
- // logger.info('Message sent', info);
238
+ const context = { id, sendOptions, sender: instance.sender };
239
+ const deliver = () => instance.transporter.sendMail(sendOptions);
196
240
 
197
- return info;
241
+ return await this.#middlewares.reduceRight((next, middleware) => () => middleware(context, next), deliver)();
198
242
  } catch (error) {
199
243
  logger.error(error, error.stack);
200
244
  return undefined;
@@ -9,7 +9,7 @@ import fs from 'fs-extra';
9
9
  import path from 'path';
10
10
  import sharp from 'sharp';
11
11
  import { Jimp, rgbaToInt } from 'jimp';
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
 
@@ -17,9 +17,9 @@ import crypto from 'crypto';
17
17
  import fs from 'fs-extra';
18
18
  import path from 'path';
19
19
  import { keccak256 as ethersKeccak256 } from 'ethers';
20
- import { loggerFactory } from '../../server/logger.js';
21
- import { shellExec } from '../../server/process.js';
22
- import { crictlCommandFactory } from '../../server/cri.js';
20
+ import { loggerFactory } from '../../server/ops/logger.js';
21
+ import { shellExec } from '../../server/runtime/process.js';
22
+ import { crictlCommandFactory } from '../../server/ops/cri.js';
23
23
 
24
24
  const logger = loggerFactory(import.meta);
25
25
 
@@ -2,7 +2,7 @@
2
2
  * Cyberia CLI content catalog.
3
3
  *
4
4
  * A per-deploy product catalog: pure data, loaded dynamically by deploy id via
5
- * {@link module:src/server/catalog} so the base build and template assembly never
5
+ * {@link module:src/server/build/catalog.js} so the base build and template assembly never
6
6
  * statically depend on it. Exports the uniform product-catalog shape:
7
7
  *
8
8
  * - `sourceMoves` — public `[src, dest]` pairs moved into the engine tree before a build.
@@ -13,12 +13,51 @@
13
13
  * - `copies` — `[src, dest]` pairs copied into the template during assembly (like moves but copied instead of moved).
14
14
  * - `keywords` — npm keywords for the standalone product CLI package.
15
15
  * - `description` — npm description for the standalone product CLI package.
16
+ * - `packageName` — npm name of the product package; the deploy id without `dd-` otherwise.
17
+ * - `packageBin` — bin map of the standalone product CLI.
18
+ * - `packageDependencies` — runtime dependencies this product adds to the engine's.
19
+ * - `packageScripts` — npm scripts this product adds to the engine's.
20
+ *
21
+ * The `package*` fields are the single declaration of what this product's manifests carry:
22
+ * every generated manifest — the deploy's `engine-private/conf/<id>/package.json`, the product
23
+ * repository's, and the published instance copy — is built from them by
24
+ * {@link module:src/server/build/package.js}. Nothing else may name them.
16
25
  *
17
26
  * @module src/projects/cyberia/catalog-cyberia.js
18
27
  * @namespace CyberiaCatalog
19
28
  */
20
29
 
30
+ const DEPLOY_ID = 'dd-cyberia';
31
+ const DOCKER_COMPOSE_ID = 'cyberia';
32
+
33
+ const dockerScript = (action, flags = '') =>
34
+ `node bin docker-compose --${action}${flags} --deploy-id ${DEPLOY_ID} --docker-compose-id ${DOCKER_COMPOSE_ID}`;
35
+
21
36
  export default {
37
+ packageName: 'cyberia',
38
+ // Pod bootstraps link this product checkout over the image CLI before continuing.
39
+ packageBin: { cyberia: 'bin/index.js', underpost: 'bin/index.js' },
40
+ // Native-dependency pin list: versions stay reproducible across CI and production deploys.
41
+ packageDependencies: {
42
+ 'adm-zip': '^0.6.0',
43
+ 'maxrects-packer': '^2.7.3',
44
+ pngjs: '^7.0.0',
45
+ jimp: '^1.6.0',
46
+ sharp: '^0.35.3',
47
+ ethers: '~6.16.0',
48
+ },
49
+ packageScripts: {
50
+ 'docker:generate': dockerScript('generate'),
51
+ 'docker:up': dockerScript('up'),
52
+ 'docker:up:build': dockerScript('up', ' --build'),
53
+ 'docker:down': dockerScript('down'),
54
+ 'docker:down:volumes': dockerScript('down', ' --volumes'),
55
+ 'docker:restart': dockerScript('restart'),
56
+ 'docker:pull': dockerScript('pull'),
57
+ 'docker:logs': dockerScript('logs'),
58
+ 'docker:status': dockerScript('status'),
59
+ 'docker:reset': dockerScript('reset'),
60
+ },
22
61
  sourceMoves: [],
23
62
  privateConfPaths: [
24
63
  /** INSTANCE_CODES */
@@ -26,6 +65,7 @@ export default {
26
65
  'cyberia-instances/amethyst-strata-expansion',
27
66
  'cyberia-sagas/amethyst-strata-expansion.json',
28
67
  'cyberia-instances/FOREST',
68
+ 'cyberia-instances/TEST',
29
69
 
30
70
  /** INSTANCE_CODES */
31
71
  ],
@@ -33,8 +73,7 @@ export default {
33
73
  '/src/grpc/cyberia',
34
74
  '/src/client/ssr/views/CyberiaServerMetrics.js',
35
75
  '/src/client/ssr/views/Cyberia404.js',
36
- '/test/cyberia-instance-conf-defaults.test.js',
37
- '/test/shape-generator.test.js',
76
+ '/test/integration/app/cyberia',
38
77
  '/src/projects/cyberia',
39
78
  '/src/runtime/cyberia-server',
40
79
  '/src/runtime/cyberia-client',
@@ -48,6 +87,14 @@ export default {
48
87
  '/.github/workflows/docker-image.cyberia-server.dev.ci.yml',
49
88
  '/.github/workflows/cyberia-client.cd.yml',
50
89
  '/.github/workflows/cyberia-server.cd.yml',
90
+ '/.github/workflows/coverall.cyberia.ci.yml',
91
+ '/bin/cyberia.js',
92
+ '/hardhat',
93
+ // The deploy scripts `run-workflow build-manifest` mirrors into each generated instance
94
+ // repository. The base template drops the whole `deploy/` tree, so the product CLI only has
95
+ // them if it packages them here.
96
+ '/deploy/cyberia-client',
97
+ '/deploy/cyberia-server',
51
98
  ],
52
99
  stripPaths: [
53
100
  './src/projects/cyberia',
@@ -55,11 +102,12 @@ export default {
55
102
  './src/runtime/cyberia-server',
56
103
  './src/runtime/cyberia-client',
57
104
  './src/runtime/engine-cyberia',
58
- './test/cyberia-instance-conf-defaults.test.js',
59
- './test/shape-generator.test.js',
105
+ './test/integration/app/cyberia',
60
106
  './src/client/public/cyberia-docs',
61
- 'bin/cyberia.js',
107
+ './bin/cyberia.js',
62
108
  './hardhat',
109
+ './deploy/cyberia-client',
110
+ './deploy/cyberia-server',
63
111
  ],
64
112
  moves: [],
65
113
  copies: [
@@ -14,7 +14,7 @@
14
14
  */
15
15
 
16
16
  import axios from 'axios';
17
- import { loggerFactory } from '../../server/logger.js';
17
+ import { loggerFactory } from '../../server/ops/logger.js';
18
18
 
19
19
  const logger = loggerFactory(import.meta);
20
20
 
@@ -18,8 +18,7 @@ import fs from 'fs-extra';
18
18
  import nodePath from 'path';
19
19
  import crypto from 'crypto';
20
20
  import { GeminiClient } from './gemini-client.js';
21
- import { computeSha256 } from './object-layer.js';
22
- import { loggerFactory } from '../../server/logger.js';
21
+ import { loggerFactory } from '../../server/ops/logger.js';
23
22
 
24
23
  const logger = loggerFactory(import.meta);
25
24
 
@@ -1632,13 +1631,13 @@ function normalizeSagaPayload(raw, { theme }) {
1632
1631
 
1633
1632
  /**
1634
1633
  * Persist normalized object-layer items into the ObjectLayer collection so they
1635
- * are editable in the viewer. Items are created with an empty (`null`) render
1636
- * and an `OFF_CHAIN` ledger; a render/ledger can be set later from
1634
+ * are editable in the viewer. New items get an empty render and an `OFF_CHAIN`
1635
+ * ledger; both can be set later from the object-layer import or from
1637
1636
  * `src/client/components/cyberia/ObjectLayerEngineViewer.js`.
1638
1637
  *
1639
- * Upserts by `data.item.id`. An existing item's render and ledger are PRESERVED
1640
- * (never clobbered back to null) only the textual stats/item fields are
1641
- * refreshed. `sha256` is recomputed over the resulting data.
1638
+ * Upserts through `ObjectLayer.upsertByItemId`, so `data.item.id` stays unique
1639
+ * and an existing item's render, ledger and CIDs are PRESERVED only the
1640
+ * textual stats/item fields are refreshed, and `sha256` is recomputed.
1642
1641
  *
1643
1642
  * @async
1644
1643
  * @param {Object} params
@@ -1647,28 +1646,20 @@ function normalizeSagaPayload(raw, { theme }) {
1647
1646
  * @returns {Promise<number>} Count of items created or updated.
1648
1647
  */
1649
1648
  async function persistObjectLayers({ objectLayers, ObjectLayer }) {
1649
+ await ObjectLayer.ensureUniqueItemIdIndex();
1650
+
1650
1651
  let count = 0;
1651
1652
  for (const ol of objectLayers) {
1652
1653
  const itemId = ol.item?.id;
1653
1654
  if (!itemId) continue;
1654
1655
 
1655
- const existing = await ObjectLayer.findOne({ 'data.item.id': itemId });
1656
-
1657
- // Preserve any render already set via the viewer; default to empty render.
1658
- const hasRender = existing?.data?.render?.cid || existing?.data?.render?.metadataCid;
1659
- const render = hasRender ? existing.data.render : { cid: null, metadataCid: null };
1660
- const ledger = existing?.data?.ledger?.type ? existing.data.ledger : { type: 'OFF_CHAIN', tokenId: '' };
1661
-
1662
- const data = { stats: ol.stats, item: ol.item, ledger, render };
1663
- const sha256 = computeSha256(data);
1664
-
1665
- if (existing) {
1666
- existing.data = data;
1667
- existing.sha256 = sha256;
1668
- await existing.save();
1669
- } else {
1670
- await ObjectLayer.create({ data, sha256, cid: null });
1671
- }
1656
+ // The saga only owns the textual/statistical fields. Ledger and render are
1657
+ // seeded on insert and never refreshed, so a re-import cannot clobber an
1658
+ // on-chain registration or a render produced by the object-layer import.
1659
+ await ObjectLayer.upsertByItemId(
1660
+ { data: { stats: ol.stats, item: ol.item } },
1661
+ { setOnInsert: { cid: null, data: { ledger: { type: 'OFF_CHAIN', tokenId: '' }, render: {} } } },
1662
+ );
1672
1663
  count++;
1673
1664
  }
1674
1665
  return count;
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  import * as grpc from '@grpc/grpc-js';
27
- import { loggerFactory } from '../../server/logger.js';
27
+ import { loggerFactory } from '../../server/ops/logger.js';
28
28
 
29
29
  const logger = loggerFactory(import.meta);
30
30