@underpostnet/cyberia 3.3.0 → 3.3.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. package/.dockerignore +1 -0
  2. package/.github/workflows/coverall.cyberia.ci.yml +34 -14
  3. package/.github/workflows/cyberia-client.cd.yml +5 -0
  4. package/.github/workflows/cyberia-server.cd.yml +5 -0
  5. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  6. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  7. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  8. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  9. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  10. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  11. package/.github/workflows/engine-cyberia.cd.yml +3 -0
  12. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  13. package/.github/workflows/ghpkg.ci.yml +35 -20
  14. package/.github/workflows/hardhat.ci.yml +12 -11
  15. package/.github/workflows/npmpkg.ci.yml +17 -15
  16. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  17. package/.github/workflows/release.cd.yml +1 -0
  18. package/.prettierignore +1 -0
  19. package/AGENTS.md +47 -0
  20. package/CHANGELOG.md +565 -2510
  21. package/CLI-HELP.md +306 -147
  22. package/Dockerfile +25 -9
  23. package/Dockerfile.dev +25 -9
  24. package/Dockerfile.test +4 -4
  25. package/README.md +21 -1
  26. package/bin/build.js +66 -41
  27. package/bin/build.template.js +8 -3
  28. package/bin/cyberia.js +308 -91
  29. package/bin/deploy.js +18 -104
  30. package/bin/index.js +308 -91
  31. package/conf.js +91 -4
  32. package/deploy/cyberia-client/deploy.sh +47 -0
  33. package/deploy/cyberia-client/package.sh +18 -0
  34. package/deploy/cyberia-client/state.sh +14 -0
  35. package/deploy/cyberia-server/deploy.sh +47 -0
  36. package/deploy/cyberia-server/package.sh +18 -0
  37. package/deploy/cyberia-server/state.sh +14 -0
  38. package/deploy/dd-cyberia/deploy.sh +6 -26
  39. package/deploy/dd-cyberia/init.sh +35 -43
  40. package/deploy/dd-cyberia/package.sh +17 -0
  41. package/deploy/dd-cyberia/state.sh +14 -0
  42. package/deploy/dd-cyberia/sync-deploy.sh +92 -170
  43. package/deploy/lib/github-actions-logging.sh +594 -0
  44. package/deploy/lib/host.sh +185 -0
  45. package/deploy/lib/state.sh +62 -0
  46. package/deploy/pwa-microservices-template/deploy.sh +12 -39
  47. package/deploy/release/deploy.sh +9 -39
  48. package/deployment.yaml +7 -2
  49. package/docker-compose.yml +7 -7
  50. package/examples/static-page/README.md +19 -19
  51. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  52. package/hardhat/hardhat.config.js +1 -6
  53. package/hardhat/package-lock.json +101 -40
  54. package/hardhat/package.json +2 -2
  55. package/manifests/alertmanager/deployment.yaml +81 -0
  56. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  57. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
  58. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
  59. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  60. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  61. package/manifests/grafana/deployment.yaml +26 -7
  62. package/manifests/grafana/kustomization.yaml +1 -0
  63. package/manifests/grafana/service.yaml +6 -1
  64. package/manifests/mariadb/pv.yaml +1 -0
  65. package/manifests/mongodb/statefulset.yaml +9 -2
  66. package/manifests/mysql/pv-pvc.yaml +14 -1
  67. package/manifests/postgresql/pv.yaml +12 -1
  68. package/manifests/postgresql/pvc.yaml +1 -0
  69. package/manifests/prometheus/deployment.yaml +18 -22
  70. package/package.json +83 -10
  71. package/scripts/event-monitor.sh +56 -0
  72. package/scripts/k3s-node-setup.sh +27 -14
  73. package/scripts/kubeadm-node-setup.sh +31 -11
  74. package/scripts/maas-setup.sh +8 -8
  75. package/scripts/selinux-normalize.sh +907 -0
  76. package/scripts/shutdown-machine.sh +843 -0
  77. package/scripts/test-monitor.sh +3 -3
  78. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
  79. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
  80. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
  81. package/src/api/core/core.controller.js +1 -1
  82. package/src/api/core/core.router.js +2 -2
  83. package/src/api/core/core.service.js +2 -2
  84. package/src/api/crypto/crypto.controller.js +1 -1
  85. package/src/api/crypto/crypto.service.js +1 -1
  86. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  87. package/src/api/cyberia-action/cyberia-action.router.js +1 -1
  88. package/src/api/cyberia-action/cyberia-action.service.js +2 -2
  89. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
  90. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
  91. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
  92. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  93. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
  94. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  95. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  96. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  97. package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
  98. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
  99. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
  100. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
  101. package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
  102. package/src/api/cyberia-instance/cyberia-fallback-world.js +8 -0
  103. package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
  104. package/src/api/cyberia-instance/cyberia-instance.controller.js +1 -1
  105. package/src/api/cyberia-instance/cyberia-instance.router.js +2 -2
  106. package/src/api/cyberia-instance/cyberia-instance.service.js +2 -2
  107. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  108. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  109. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
  110. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  111. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  112. package/src/api/cyberia-map/cyberia-map.service.js +2 -2
  113. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  114. package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
  115. package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
  116. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  117. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  118. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  119. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  120. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  121. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  122. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +0 -26
  123. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  124. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  125. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  126. package/src/api/default/default.controller.js +1 -1
  127. package/src/api/default/default.router.js +1 -1
  128. package/src/api/default/default.service.js +2 -2
  129. package/src/api/document/document.controller.js +1 -1
  130. package/src/api/document/document.router.js +1 -1
  131. package/src/api/document/document.service.js +2 -2
  132. package/src/api/file/file.controller.js +1 -1
  133. package/src/api/file/file.router.js +1 -1
  134. package/src/api/file/file.service.js +2 -2
  135. package/src/api/instance/instance.controller.js +1 -1
  136. package/src/api/instance/instance.router.js +1 -1
  137. package/src/api/instance/instance.service.js +2 -2
  138. package/src/api/ipfs/ipfs.controller.js +1 -1
  139. package/src/api/ipfs/ipfs.router.js +2 -2
  140. package/src/api/ipfs/ipfs.service.js +2 -2
  141. package/src/api/object-layer/object-layer.controller.js +1 -1
  142. package/src/api/object-layer/object-layer.router.js +2 -2
  143. package/src/api/object-layer/object-layer.service.js +3 -3
  144. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  145. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  146. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  147. package/src/api/test/test.controller.js +1 -1
  148. package/src/api/test/test.service.js +1 -1
  149. package/src/api/user/guest.service.js +3 -3
  150. package/src/api/user/user.controller.js +1 -1
  151. package/src/api/user/user.router.js +2 -2
  152. package/src/api/user/user.service.js +4 -4
  153. package/src/api.js +5 -9
  154. package/src/cli/app.js +391 -0
  155. package/src/cli/baremetal.js +30 -35
  156. package/src/cli/client.js +306 -0
  157. package/src/cli/cloud-init.js +3 -3
  158. package/src/cli/cluster.js +184 -82
  159. package/src/cli/db.js +120 -68
  160. package/src/cli/deploy.js +153 -71
  161. package/src/cli/docker-compose.js +5 -5
  162. package/src/cli/domains.js +184 -0
  163. package/src/cli/dotenv-store.js +143 -0
  164. package/src/cli/event.js +2281 -0
  165. package/src/cli/fs.js +3 -3
  166. package/src/cli/host.js +672 -0
  167. package/src/cli/image.js +4 -6
  168. package/src/cli/index.js +322 -142
  169. package/src/cli/ipfs.js +34 -30
  170. package/src/cli/kickstart.js +1 -1
  171. package/src/cli/kubectl.js +218 -41
  172. package/src/cli/lxd.js +3 -3
  173. package/src/cli/monitor.js +1359 -26
  174. package/src/cli/package.js +90 -0
  175. package/src/cli/release.js +16 -12
  176. package/src/cli/repository.js +558 -363
  177. package/src/cli/run.js +331 -650
  178. package/src/cli/secrets.js +2158 -964
  179. package/src/cli/ssh.js +478 -279
  180. package/src/cli/state.js +394 -0
  181. package/src/cli/static.js +2 -2
  182. package/src/cli/system.js +1 -1
  183. package/src/cli/test.js +199 -125
  184. package/src/cli/vultr.js +61 -21
  185. package/src/cli/wireguard.js +1111 -306
  186. package/src/client/components/core/CalendarCore.js +53 -96
  187. package/src/client/components/core/Docs.js +258 -211
  188. package/src/client/components/core/FileExplorer.js +0 -21
  189. package/src/client/components/core/PanelForm.js +4 -4
  190. package/src/client/components/core/Repository.js +56 -0
  191. package/src/client/components/core/Translate.js +7 -0
  192. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  193. package/src/client/components/core/Wallet.js +0 -11
  194. package/src/client/components/core/Worker.js +7 -1
  195. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  196. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -1
  197. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  198. package/src/client/components/default/AppShellDefault.js +1 -1
  199. package/src/client/components/default/SettingsDefault.js +2 -2
  200. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  201. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  202. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  203. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
  204. package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
  205. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  206. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  207. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  208. package/src/client/public/default/android-chrome-144x144.png +0 -0
  209. package/src/client/public/default/android-chrome-192x192.png +0 -0
  210. package/src/client/public/default/android-chrome-256x256.png +0 -0
  211. package/src/client/public/default/android-chrome-36x36.png +0 -0
  212. package/src/client/public/default/android-chrome-384x384.png +0 -0
  213. package/src/client/public/default/android-chrome-48x48.png +0 -0
  214. package/src/client/public/default/android-chrome-512x512.png +0 -0
  215. package/src/client/public/default/android-chrome-72x72.png +0 -0
  216. package/src/client/public/default/android-chrome-96x96.png +0 -0
  217. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  218. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  219. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  220. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  221. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  222. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  223. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  224. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  225. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  226. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  227. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  228. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  229. package/src/client/public/default/apple-touch-icon.png +0 -0
  230. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  231. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  232. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  233. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  234. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  235. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  236. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  237. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  238. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  239. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  240. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  241. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  242. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  243. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  244. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  245. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  246. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  247. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  248. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  249. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  250. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  251. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  252. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  253. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  254. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  255. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  256. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  257. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  258. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  259. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  260. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  261. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  262. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  263. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  264. package/src/client/public/default/assets/background/white.jpg +0 -0
  265. package/src/client/public/default/browserconfig.xml +1 -1
  266. package/src/client/public/default/favicon-16x16.png +0 -0
  267. package/src/client/public/default/favicon-32x32.png +0 -0
  268. package/src/client/public/default/favicon-48x48.png +0 -0
  269. package/src/client/public/default/favicon.ico +0 -0
  270. package/src/client/public/default/manifest.webmanifest +5 -5
  271. package/src/client/public/default/mstile-144x144.png +0 -0
  272. package/src/client/public/default/mstile-150x150.png +0 -0
  273. package/src/client/public/default/mstile-310x150.png +0 -0
  274. package/src/client/public/default/mstile-310x310.png +0 -0
  275. package/src/client/public/default/mstile-70x70.png +0 -0
  276. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  277. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  278. package/src/client/ssr/RootDocument.js +1 -1
  279. package/src/client/ssr/body/404.js +1 -1
  280. package/src/client/ssr/body/500.js +1 -1
  281. package/src/client/ssr/body/CacheControl.js +1 -1
  282. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  283. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  284. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  285. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  286. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  287. package/src/client/ssr/head/Css.js +1 -1
  288. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  289. package/src/client/ssr/head/DefaultScripts.js +1 -1
  290. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  291. package/src/client/ssr/head/Microdata.js +1 -1
  292. package/src/client/ssr/head/Production.js +1 -1
  293. package/src/client/ssr/head/Pwa.js +1 -1
  294. package/src/client/ssr/head/PwaItemledger.js +1 -1
  295. package/src/client/ssr/head/Seo.js +1 -1
  296. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  297. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  298. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  299. package/src/client/ssr/views/Cyberia404.js +7 -5
  300. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  301. package/src/client/ssr/views/Maintenance.js +1 -1
  302. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  303. package/src/client/ssr/views/Test.js +1 -1
  304. package/src/client/sw/core.sw.js +20 -14
  305. package/src/client-builder/client-build-docs.js +61 -46
  306. package/src/client-builder/client-build-live.js +2 -2
  307. package/src/client-builder/client-build.js +38 -30
  308. package/src/client-builder/client-dev-server.js +3 -3
  309. package/src/client-builder/client-icons.js +2 -2
  310. package/src/client-builder/ssr.js +3 -3
  311. package/src/client.build.js +3 -6
  312. package/src/client.dev.js +3 -6
  313. package/src/db/DataBaseProvider.js +186 -3
  314. package/src/db/mariadb/MariaDB.js +3 -2
  315. package/src/db/mongo/MongoBootstrap.js +273 -101
  316. package/src/db/mongo/MongooseDB.js +7 -8
  317. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  318. package/src/grpc/cyberia/grpc-server.js +1 -1
  319. package/src/index.js +79 -23
  320. package/src/mailer/EmailRender.js +2 -2
  321. package/src/mailer/MailerInterceptor.js +87 -0
  322. package/src/mailer/MailerProvider.js +50 -6
  323. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
  324. package/src/projects/cyberia/besu-genesis-generator.js +3 -3
  325. package/src/projects/cyberia/catalog-cyberia.js +53 -10
  326. package/src/projects/cyberia/gemini-client.js +1 -1
  327. package/src/projects/cyberia/generate-saga.js +1 -1
  328. package/src/projects/cyberia/hot-reload-trigger.js +1 -1
  329. package/src/projects/cyberia/instance-data.js +1 -1
  330. package/src/projects/cyberia/ipfs-client.js +4 -4
  331. package/src/projects/cyberia/map-preview-generator.js +1 -1
  332. package/src/projects/cyberia/object-layer.js +1 -1
  333. package/src/projects/cyberia/semantic-layer-generator.js +1 -1
  334. package/src/projects/underpost/catalog-underpost.js +9 -1
  335. package/src/proxy.js +4 -7
  336. package/src/runtime/cyberia-client/Dockerfile +9 -4
  337. package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
  338. package/src/runtime/cyberia-server/Dockerfile +9 -4
  339. package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
  340. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  341. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  342. package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
  343. package/src/runtime/engine-cyberia/docker-compose.yml +7 -7
  344. package/src/runtime/express/Express.js +32 -27
  345. package/src/runtime/lampp/Lampp.js +22 -70
  346. package/src/runtime/nginx/Nginx.js +1 -1
  347. package/src/runtime/wp/Wp.js +16 -48
  348. package/src/server/{catalog.js → build/catalog.js} +15 -5
  349. package/src/server/build/coverage.js +117 -0
  350. package/src/server/build/execution.js +402 -0
  351. package/src/server/build/package.js +465 -0
  352. package/src/server/build/testing.js +528 -0
  353. package/src/server/{dns.js → network/dns.js} +144 -11
  354. package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
  355. package/src/server/{middlewares.js → network/middlewares.js} +3 -3
  356. package/src/server/network/node-capability.js +98 -0
  357. package/src/server/{peer.js → network/peer.js} +3 -3
  358. package/src/server/{proxy.js → network/proxy.js} +7 -13
  359. package/src/server/network/router.js +356 -0
  360. package/src/server/{tls.js → network/tls.js} +2 -2
  361. package/src/server/{underpost-compression.js → network/underpost-compression.js} +1 -1
  362. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
  363. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
  364. package/src/server/{cri.js → ops/cri.js} +2 -2
  365. package/src/server/{cron.js → ops/cron.js} +349 -74
  366. package/src/server/ops/event-notification.js +284 -0
  367. package/src/server/{logger.js → ops/logger.js} +108 -23
  368. package/src/server/ops/monitoring.js +1724 -0
  369. package/src/server/{systemd.js → ops/systemd.js} +55 -1
  370. package/src/server/{conf.js → runtime/conf.js} +513 -422
  371. package/src/server/runtime/config-scope.js +215 -0
  372. package/src/server/runtime/environment.js +149 -0
  373. package/src/server/{process.js → runtime/process.js} +153 -12
  374. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  375. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  376. package/src/server/{start.js → runtime/start.js} +128 -39
  377. package/src/server/{auth.js → security/auth.js} +7 -8
  378. package/src/server/security/container-storage.js +382 -0
  379. package/src/server/{crypto.js → security/crypto.js} +1 -1
  380. package/src/server/{selinux.js → security/selinux.js} +1 -1
  381. package/src/server/{backup.js → storage/backup.js} +17 -8
  382. package/src/server/{data-query.js → storage/data-query.js} +1 -1
  383. package/src/server/{downloader.js → storage/downloader.js} +2 -2
  384. package/src/server/storage/repository.js +68 -0
  385. package/src/server.js +4 -7
  386. package/src/ws/IoInterface.js +1 -1
  387. package/src/ws/IoServer.js +1 -1
  388. package/src/ws/core/core.ws.connection.js +1 -1
  389. package/src/ws/core/core.ws.emit.js +1 -1
  390. package/src/ws/core/core.ws.server.js +1 -1
  391. package/src/ws/default/default.ws.connection.js +1 -1
  392. package/src/ws/default/default.ws.emit.js +1 -1
  393. package/src/ws/default/default.ws.server.js +1 -1
  394. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  395. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  396. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  397. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  398. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
  399. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +1 -1
  400. package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
  401. package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
  402. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  403. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  404. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  405. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  406. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  407. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  408. package/test/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
  409. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  410. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  411. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  412. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  413. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  414. package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
  415. package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +609 -55
  416. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  417. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  418. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  419. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  420. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  421. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  422. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +6 -6
  423. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -4
  424. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  425. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  426. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  427. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  428. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  429. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  430. package/test/support/shell-harness.js +73 -0
  431. package/test/unit/build-template.test.js +97 -0
  432. package/test/unit/build-workflow-offline.test.js +132 -0
  433. package/test/unit/catalog.test.js +71 -0
  434. package/test/unit/client-build-docs.test.js +334 -0
  435. package/test/unit/conf-loading.test.js +303 -0
  436. package/test/unit/conf-resolution.test.js +979 -0
  437. package/test/unit/coverage-artifact.test.js +130 -0
  438. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  439. package/test/unit/deploy-env-resolution.test.js +38 -0
  440. package/test/unit/deploy-log-table.test.js +447 -0
  441. package/test/unit/execution-profiles.test.js +219 -0
  442. package/test/unit/fleet-sync-source.test.js +149 -0
  443. package/test/unit/logger-redaction.test.js +112 -0
  444. package/test/unit/package.test.js +403 -0
  445. package/test/unit/prepare-host.test.js +299 -0
  446. package/test/unit/process-environment.test.js +18 -0
  447. package/test/unit/propagation-message.test.js +78 -0
  448. package/test/unit/redeploy-plan.test.js +24 -0
  449. package/test/unit/release-bump.test.js +474 -0
  450. package/test/unit/ssh-output-redaction.test.js +28 -0
  451. package/test/unit/start-options.test.js +46 -0
  452. package/test/unit/test-tiers.test.js +193 -0
  453. package/vitest.config.js +58 -0
  454. package/.nycrc +0 -9
  455. package/deploy/lib/logging.sh +0 -96
  456. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  457. package/manifests/mongodb/pv-pvc.yaml +0 -59
  458. package/scripts/coverall-test-cyberia.sh +0 -24
  459. package/scripts/coverall-test.sh +0 -24
  460. package/scripts/link-local-underpost-cli.sh +0 -6
  461. package/src/api/user/user.build.js +0 -16
  462. package/src/cli/env.js +0 -177
  463. package/src/client/components/core/Blockchain.js +0 -41
  464. package/src/client/components/core/Blog.js +0 -9
  465. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  466. package/src/client/public/default/assets/background/dark.jpg +0 -0
  467. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  468. package/src/client/public/default/assets/background/white0.jpg +0 -0
  469. package/src/client/public/doc/favicon.ico +0 -0
  470. package/src/client/public/doc/sitemap +0 -148
  471. package/src/server/environment.js +0 -98
@@ -0,0 +1,528 @@
1
+ /**
2
+ * The test tier contract: which suites exist, the order they run in, and the
3
+ * in-cluster surfaces that execute and report them.
4
+ *
5
+ * Tiers are a lifecycle, not a taxonomy. A gateway assertion that fails because
6
+ * SELinux denied a bind is a security failure reported at the ingress layer, so
7
+ * the lower tier has to have run — and passed — before the higher one is worth
8
+ * reading. Vitest expresses that with one project per tier and an ascending
9
+ * `sequence.groupOrder`; nothing outside this table decides what runs when.
10
+ *
11
+ * This module is pure: it renders the runner configuration, the argument vector
12
+ * and the manifests from values it is given. Resolving deploy configuration,
13
+ * spawning the runner and talking to the cluster belong to `src/cli/test.js`.
14
+ *
15
+ * @module src/server/build/testing.js
16
+ * @namespace UnderpostTesting
17
+ */
18
+
19
+ /**
20
+ * @constant UNDERPOST_TESTING
21
+ * @description Identity of the test execution and reporting surfaces. One
22
+ * dashboard serves every deploy on the cluster, so these names are cluster-wide
23
+ * constants rather than per-deploy.
24
+ * @memberof UnderpostTesting
25
+ */
26
+ const UNDERPOST_TESTING = {
27
+ coverageDirectory: 'coverage',
28
+ lcovPath: 'coverage/lcov.info',
29
+ // Minimum total line coverage a gated run must reach — the same metric Coveralls
30
+ // reports, so a green build and a green badge mean the same thing. It is a
31
+ // ratchet: the floor the measured surface already holds (85% for the platform
32
+ // tiers, 85% with cyberia), raised as suites land, never a target no run meets.
33
+ // `COVERAGE_MIN` moves it for one repository without moving it for every one.
34
+ coverageThreshold: 80,
35
+ // Read by vitest.config.js to decide whether the Allure reporter is attached.
36
+ // Absent means a plain local run, so no result files are written at all.
37
+ allureResultsEnvKey: 'UNDERPOST_ALLURE_RESULTS',
38
+ allureResultsDirectory: 'allure-results',
39
+ allure: {
40
+ name: 'allure',
41
+ image: 'frankescobar/allure-docker-service:2.27.0',
42
+ port: 5050,
43
+ nodePort: 32350,
44
+ pvcName: 'allure-pvc',
45
+ pvcStorage: '2Gi',
46
+ resultsPath: '/app/allure-results',
47
+ reportsPath: '/app/default-reports',
48
+ routeName: 'allure-route',
49
+ // Sub-path under an existing hostname, so the dashboard rides the edge
50
+ // certificate already issued for that host instead of needing one of its own.
51
+ subPath: '/allure',
52
+ // Reports are rebuilt from the results directory on this cadence, which is
53
+ // how a Job that finishes after the page is open still shows up.
54
+ checkResultsEverySeconds: 5,
55
+ keepHistory: true,
56
+ },
57
+ job: {
58
+ namePrefix: 'underpost-test',
59
+ // A test run is a diagnostic, not a workload: a crash loop would hide the
60
+ // failure it is meant to report.
61
+ restartPolicy: 'Never',
62
+ backoffLimit: 0,
63
+ ttlSecondsAfterFinished: 3600,
64
+ workingDirectory: '/home/dd/engine',
65
+ },
66
+ };
67
+
68
+ /**
69
+ * @constant TEST_TIERS
70
+ * @description Every runnable tier, in lifecycle order.
71
+ *
72
+ * `name` doubles as the Vitest project id, and its prefix before `:` is the
73
+ * suite it belongs to — so `--suite infra` needs no second table to expand.
74
+ *
75
+ * `groupOrder` is what Vitest sequences on: equal values run in parallel, lower
76
+ * values run to completion first. It starts at 1, never 0 — Vitest routes a
77
+ * project left on the default 0 with a single worker into a bucket it appends
78
+ * after every ordered group, which would run the first tier last.
79
+ *
80
+ * A tier with a `delegate` runs on its own runner instead of as a Vitest
81
+ * project, after the Vitest run — so a delegated tier belongs in the last
82
+ * group, where the order it is declared in still matches the order it runs in.
83
+ *
84
+ * `sources` are the modules the tier's suites drive directly, and they are what
85
+ * coverage is measured over when the tier is selected. A module reached only as
86
+ * a collaborator — everything the `src/index.js` barrel pulls in behind one CLI
87
+ * call, everything a suite spawns into its own process — belongs to whichever
88
+ * tier asserts against it, or to none: counting it here reports a floor no test
89
+ * in the selection can move. A delegated tier declares none, because its runner
90
+ * reports its own coverage.
91
+ * @memberof UnderpostTesting
92
+ */
93
+ const TEST_TIERS = [
94
+ {
95
+ name: 'unit',
96
+ directory: 'test/unit',
97
+ groupOrder: 1,
98
+ sources: [
99
+ 'conf.js',
100
+ 'src/cli/release.js',
101
+ 'src/client-builder/client-build-docs.js',
102
+ 'src/projects/underpost/*.js',
103
+ 'src/server/runtime/conf.js',
104
+ 'src/server/security/crypto.js',
105
+ ],
106
+ description: 'Pure functions with no host, cluster or network dependency.',
107
+ },
108
+ {
109
+ name: 'infra:1-security',
110
+ directory: 'test/integration/infra/1-security',
111
+ groupOrder: 2,
112
+ sources: [
113
+ 'src/cli/secrets.js',
114
+ 'src/server/ops/systemd.js',
115
+ 'src/server/security/container-storage.js',
116
+ 'src/server/security/selinux.js',
117
+ ],
118
+ description: 'SELinux policy, systemd units and the SOPS secret store.',
119
+ },
120
+ {
121
+ name: 'infra:2-network',
122
+ directory: 'test/integration/infra/2-network',
123
+ groupOrder: 3,
124
+ sources: ['src/cli/wireguard.js', 'src/server/network/dns.js', 'src/server/network/forward-proxy.js'],
125
+ description: 'WireGuard edge connectivity the cluster is reachable over.',
126
+ },
127
+ {
128
+ name: 'infra:3-cluster',
129
+ directory: 'test/integration/infra/3-cluster',
130
+ groupOrder: 4,
131
+ sources: ['src/cli/docker-compose.js', 'src/server/runtime/conf.js'],
132
+ description: 'Instance clustering, node assignment and compute scheduling.',
133
+ },
134
+ {
135
+ name: 'infra:4-ingress',
136
+ directory: 'test/integration/infra/4-ingress',
137
+ groupOrder: 5,
138
+ sources: [
139
+ 'src/server/network/router.js',
140
+ 'src/server/network/underpost-compression.js',
141
+ 'src/server/network/underpost-gateway.js',
142
+ 'src/server/network/underpost-ingress.js',
143
+ 'src/server/runtime/conf.js',
144
+ ],
145
+ description: 'Gateways, ingress controllers, deploy routes and traffic plans.',
146
+ },
147
+ {
148
+ name: 'infra:5-observability',
149
+ directory: 'test/integration/infra/5-observability',
150
+ groupOrder: 6,
151
+ sources: [
152
+ 'src/cli/event.js',
153
+ 'src/mailer/*.js',
154
+ 'src/server/ops/cron.js',
155
+ 'src/server/ops/event-notification.js',
156
+ 'src/server/ops/monitoring.js',
157
+ 'src/server/runtime/runtime-status.js',
158
+ ],
159
+ description: 'Monitoring stack, deploy monitor, notifications and remediation.',
160
+ },
161
+ {
162
+ name: 'app',
163
+ directory: 'test/integration/app',
164
+ groupOrder: 7,
165
+ sources: ['src/api/test/*.js', 'src/server/ops/logger.js'],
166
+ // Non-recursive: the cyberia extension underneath is its own tier, because
167
+ // it ships in a separate product CLI and must stay separately runnable.
168
+ recursive: false,
169
+ description: 'Platform application layer served over the provisioned stack.',
170
+ },
171
+ {
172
+ name: 'cyberia',
173
+ directory: 'test/integration/app/cyberia',
174
+ groupOrder: 7,
175
+ sources: [
176
+ 'src/api/cyberia-server-defaults/*.js',
177
+ 'src/api/cyberia-instance/cyberia-fallback-capture.js',
178
+ 'src/api/object-layer/object-layer.model.js',
179
+ 'src/projects/cyberia/shape-generator.js',
180
+ ],
181
+ description: 'Cyberia MMO extension: content, persistence and shape generation.',
182
+ },
183
+ {
184
+ name: 'contracts',
185
+ directory: 'hardhat',
186
+ groupOrder: 7,
187
+ description: 'ObjectLayerToken ERC-1155 behaviour on the in-process EVM.',
188
+ // Hardhat owns Solidity compilation and the EVM these run against, so they
189
+ // cannot be collected by Vitest. Hardhat's own `test` task pins a reporter
190
+ // with no machine-readable output, so the suites — plain `node:test` files —
191
+ // are run on Node's runner directly, which can emit the JUnit results the
192
+ // dashboard ingests while still printing a readable run.
193
+ delegate: ({ resultsPath = '', grep = '' } = {}) =>
194
+ [
195
+ '[ -x node_modules/.bin/hardhat ] || npm ci --no-audit --no-fund',
196
+ './node_modules/.bin/hardhat build',
197
+ [
198
+ // Set by Hardhat's own test task; plugins branch on them.
199
+ 'HH_TEST=true NODE_ENV=test node --test',
200
+ '--test-reporter=spec --test-reporter-destination=stdout',
201
+ ...(resultsPath ? [`--test-reporter=junit --test-reporter-destination=${resultsPath}`] : []),
202
+ ...(grep ? [`--test-name-pattern=${JSON.stringify(grep)}`] : []),
203
+ "'test/**/*.js'",
204
+ ].join(' '),
205
+ ].join(' && '),
206
+ },
207
+ ];
208
+
209
+ /**
210
+ * @method testSuiteNames
211
+ * @description Suite selectors `--suite` accepts, derived from the tier names
212
+ * so a new tier is selectable the moment it is declared.
213
+ * @returns {string[]} Suite names, plus the `all` selector.
214
+ * @memberof UnderpostTesting
215
+ */
216
+ const testSuiteNames = () => [...new Set(TEST_TIERS.map(({ name }) => name.split(':')[0])), 'all'];
217
+
218
+ /**
219
+ * @method resolveTestTiers
220
+ * @description Expands a comma separated selector into tiers.
221
+ *
222
+ * Expansion happens here rather than being passed through as a glob so an
223
+ * unknown selector fails with the list of valid ones instead of silently
224
+ * matching nothing and reporting a green run.
225
+ * @param {string} [selector] - Suite names, tier names, or empty for every tier.
226
+ * @returns {object[]} Selected tiers, in declaration order.
227
+ * @throws {Error} When a selector matches no declared tier.
228
+ * @memberof UnderpostTesting
229
+ */
230
+ const resolveTestTiers = (selector = '') => {
231
+ const selectors = selector
232
+ .split(',')
233
+ .map((value) => value.trim())
234
+ .filter(Boolean);
235
+ if (selectors.length === 0 || selectors.includes('all')) return TEST_TIERS;
236
+
237
+ const selected = new Set();
238
+ for (const value of selectors) {
239
+ const matched = TEST_TIERS.filter(({ name }) => name === value || name.startsWith(`${value}:`));
240
+ if (matched.length === 0)
241
+ throw new Error(
242
+ `[test] unknown suite '${value}' — expected one of ${testSuiteNames().join(', ')} ` +
243
+ `or a tier: ${TEST_TIERS.map(({ name }) => name).join(', ')}`,
244
+ );
245
+ for (const tier of matched) selected.add(tier);
246
+ }
247
+ return TEST_TIERS.filter((tier) => selected.has(tier));
248
+ };
249
+
250
+ /**
251
+ * @method resolveTestSelection
252
+ * @description Splits a selector into the two runners that serve it.
253
+ * @param {string} [selector] - Suite names, tier names, or empty for every tier.
254
+ * @returns {{projects: string[], runVitest: boolean, delegated: object[]}} Selection.
255
+ * @throws {Error} When a selector matches no declared tier.
256
+ * @memberof UnderpostTesting
257
+ */
258
+ const resolveTestSelection = (selector = '') => {
259
+ const tiers = resolveTestTiers(selector);
260
+ const vitestTiers = tiers.filter(({ delegate }) => !delegate);
261
+ const everyVitestTier = vitestTiers.length === TEST_TIERS.filter(({ delegate }) => !delegate).length;
262
+ return {
263
+ // No `--project` flags when every tier is selected: Vitest runs them all by
264
+ // default, and an explicit list would fail a template that strips one.
265
+ projects: everyVitestTier ? [] : vitestTiers.map(({ name }) => name),
266
+ runVitest: vitestTiers.length > 0,
267
+ delegated: tiers.filter(({ delegate }) => delegate),
268
+ };
269
+ };
270
+
271
+ /**
272
+ * @method testProjectsFactory
273
+ * @description Renders the Vitest `projects` array from the tier table.
274
+ *
275
+ * A Vitest project is a standalone configuration and inherits nothing from the
276
+ * root `test` block, so whatever every tier needs is spread in here rather than
277
+ * declared once at the root and silently dropped.
278
+ * @param {object} [defaults] - Per-project `test` options shared by every tier.
279
+ * @returns {object[]} Vitest inline project configurations.
280
+ * @memberof UnderpostTesting
281
+ */
282
+ const testProjectsFactory = (defaults = {}) =>
283
+ TEST_TIERS.filter(({ delegate }) => !delegate).map(({ name, directory, groupOrder, recursive = true }) => ({
284
+ test: {
285
+ ...defaults,
286
+ name,
287
+ include: [`${directory}/${recursive ? '**/' : ''}*.test.js`],
288
+ sequence: { ...defaults.sequence, groupOrder },
289
+ },
290
+ }));
291
+
292
+ /**
293
+ * @method vitestArgsFactory
294
+ * @description Builds the Vitest argument vector for one run.
295
+ * @param {object} [params]
296
+ * @param {string[]} [params.projects] - Vitest project ids, empty for every project.
297
+ * @param {string} [params.grep] - Substring filter on test names.
298
+ * @param {boolean} [params.watch] - Keep the runner open and re-run on change.
299
+ * @param {boolean} [params.coverage] - Emit the coverage reporters.
300
+ * @returns {string[]} Arguments for the `vitest` binary.
301
+ * @memberof UnderpostTesting
302
+ */
303
+ const vitestArgsFactory = ({ projects = [], grep = '', watch = false, coverage = true } = {}) => [
304
+ // Subcommands, not flags: `vitest run --watch` is contradictory and Vitest
305
+ // resolves it to a single non-watching run.
306
+ watch ? 'watch' : 'run',
307
+ ...projects.flatMap((project) => ['--project', project]),
308
+ ...(grep ? ['--testNamePattern', grep] : []),
309
+ ...(coverage ? ['--coverage'] : ['--coverage.enabled=false']),
310
+ ];
311
+
312
+ /**
313
+ * @method coverageThresholdFactory
314
+ * @description Resolves the minimum total line coverage a run must reach, or `null`
315
+ * when the run reports without gating.
316
+ *
317
+ * Gating is opt-in because a tier selection measures a slice of the tree: holding
318
+ * every partial local run to the whole-suite number would fail runs that never
319
+ * loaded the code being counted. `npm run test:coverage` and CI opt in; `COVERAGE_MIN`
320
+ * lowers the bar for a repository whose suite is still catching up to it.
321
+ * @param {object} [env] - Environment to read `COVERAGE_ENFORCE` and `COVERAGE_MIN` from.
322
+ * @returns {number|null} Threshold percentage, or `null` to report without gating.
323
+ * @throws {Error} When `COVERAGE_MIN` is not a percentage.
324
+ * @memberof UnderpostTesting
325
+ */
326
+ const coverageThresholdFactory = ({ COVERAGE_ENFORCE, COVERAGE_MIN } = {}) => {
327
+ if (COVERAGE_MIN !== undefined && COVERAGE_MIN !== '') {
328
+ const threshold = Number(COVERAGE_MIN);
329
+ if (!Number.isFinite(threshold) || threshold < 0 || threshold > 100)
330
+ throw new Error(`[test] COVERAGE_MIN must be a percentage between 0 and 100, got '${COVERAGE_MIN}'`);
331
+ return threshold;
332
+ }
333
+ return COVERAGE_ENFORCE === '1' || COVERAGE_ENFORCE === 'true' ? UNDERPOST_TESTING.coverageThreshold : null;
334
+ };
335
+
336
+ /**
337
+ * @method coverageIncludeFactory
338
+ * @description Source globs a run measures coverage over, from the tier selection
339
+ * on its own command line.
340
+ *
341
+ * Read from the argument vector rather than passed in, because the runner's config
342
+ * is loaded by the Vitest process the arguments were handed to — a `--project` the
343
+ * caller added by hand is as authoritative as one `vitestArgsFactory` rendered.
344
+ * @param {string[]} [argv] - Argument vector carrying the `--project` selection.
345
+ * @returns {string[]} Globs for `coverage.include`, every selected tier's sources.
346
+ * @throws {Error} When a selected project matches no declared tier.
347
+ * @memberof UnderpostTesting
348
+ */
349
+ const coverageIncludeFactory = (argv = []) => {
350
+ const projects = argv.flatMap((arg, index) =>
351
+ arg === '--project' ? [argv[index + 1]] : arg.startsWith('--project=') ? [arg.slice('--project='.length)] : [],
352
+ );
353
+ return [...new Set(resolveTestTiers(projects.filter(Boolean).join(',')).flatMap(({ sources = [] }) => sources))];
354
+ };
355
+
356
+ /**
357
+ * @method allureManifestsFactory
358
+ * @description Renders the Allure dashboard: a claim for the results the runs
359
+ * write, the report server, and the ways in.
360
+ *
361
+ * The server watches the results directory rather than being pushed a report,
362
+ * so a Job that writes its results and exits needs no callback and no ordering
363
+ * against the dashboard's own lifecycle.
364
+ * @param {object} params
365
+ * @param {string} params.namespace - Target namespace.
366
+ * @param {string} [params.host] - Hostname to route `/allure` on; omitted means NodePort only.
367
+ * @returns {string} Concatenated YAML documents.
368
+ * @memberof UnderpostTesting
369
+ */
370
+ const allureManifestsFactory = ({ namespace, host = '' }) => {
371
+ const { allure } = UNDERPOST_TESTING;
372
+ const manifests = [
373
+ `apiVersion: v1
374
+ kind: PersistentVolumeClaim
375
+ metadata:
376
+ name: ${allure.pvcName}
377
+ namespace: ${namespace}
378
+ spec:
379
+ accessModes:
380
+ - ReadWriteOnce
381
+ resources:
382
+ requests:
383
+ storage: ${allure.pvcStorage}`,
384
+ `apiVersion: apps/v1
385
+ kind: Deployment
386
+ metadata:
387
+ name: ${allure.name}
388
+ namespace: ${namespace}
389
+ spec:
390
+ replicas: 1
391
+ selector:
392
+ matchLabels:
393
+ app: ${allure.name}
394
+ template:
395
+ metadata:
396
+ labels:
397
+ app: ${allure.name}
398
+ spec:
399
+ containers:
400
+ - name: ${allure.name}
401
+ image: ${allure.image}
402
+ ports:
403
+ - containerPort: ${allure.port}
404
+ env:
405
+ - name: CHECK_RESULTS_EVERY_SECONDS
406
+ value: '${allure.checkResultsEverySeconds}'
407
+ - name: KEEP_HISTORY
408
+ value: '${allure.keepHistory ? 1 : 0}'
409
+ - name: URL_PREFIX
410
+ value: '${host ? allure.subPath : ''}'
411
+ volumeMounts:
412
+ - name: results
413
+ mountPath: ${allure.resultsPath}
414
+ - name: reports
415
+ mountPath: ${allure.reportsPath}
416
+ readinessProbe:
417
+ httpGet:
418
+ path: ${host ? allure.subPath : ''}/allure-docker-service/version
419
+ port: ${allure.port}
420
+ initialDelaySeconds: 10
421
+ periodSeconds: 10
422
+ volumes:
423
+ - name: results
424
+ persistentVolumeClaim:
425
+ claimName: ${allure.pvcName}
426
+ - name: reports
427
+ emptyDir: {}`,
428
+ `apiVersion: v1
429
+ kind: Service
430
+ metadata:
431
+ name: ${allure.name}
432
+ namespace: ${namespace}
433
+ spec:
434
+ type: NodePort
435
+ selector:
436
+ app: ${allure.name}
437
+ ports:
438
+ - port: ${allure.port}
439
+ targetPort: ${allure.port}
440
+ nodePort: ${allure.nodePort}`,
441
+ ];
442
+
443
+ if (host)
444
+ manifests.push(`apiVersion: projectcontour.io/v1
445
+ kind: HTTPProxy
446
+ metadata:
447
+ name: ${allure.routeName}
448
+ namespace: ${namespace}
449
+ spec:
450
+ virtualhost:
451
+ fqdn: ${host}
452
+ tls:
453
+ secretName: ${host}
454
+ routes:
455
+ - conditions:
456
+ - prefix: ${allure.subPath}
457
+ services:
458
+ - name: ${allure.name}
459
+ port: ${allure.port}`);
460
+
461
+ return manifests.join('\n---\n');
462
+ };
463
+
464
+ /**
465
+ * @method testJobManifestFactory
466
+ * @description Renders a Job that runs one suite inside the cluster.
467
+ *
468
+ * The Job mounts the same results claim the dashboard reads, so its output is
469
+ * on the dashboard the moment it exits — no artifact upload step, and no
470
+ * dependency on the Job's own pod outliving the run.
471
+ * @param {object} params
472
+ * @param {string} params.name - Job name.
473
+ * @param {string} params.namespace - Target namespace.
474
+ * @param {string} params.image - Image carrying the engine and its dependencies.
475
+ * @param {string} params.suite - Suite or tier selector passed to `underpost test`.
476
+ * @param {string} [params.nodeName] - Pins the pod to one node.
477
+ * @returns {string} Job YAML.
478
+ * @memberof UnderpostTesting
479
+ */
480
+ const testJobManifestFactory = ({ name, namespace, image, suite, nodeName = '' }) => {
481
+ const { allure, job } = UNDERPOST_TESTING;
482
+ const command = ['underpost', 'test', ...(suite ? [suite] : []), '--itc', '--allure'].join(' ');
483
+ return `apiVersion: batch/v1
484
+ kind: Job
485
+ metadata:
486
+ name: ${name}
487
+ namespace: ${namespace}
488
+ spec:
489
+ backoffLimit: ${job.backoffLimit}
490
+ ttlSecondsAfterFinished: ${job.ttlSecondsAfterFinished}
491
+ template:
492
+ metadata:
493
+ labels:
494
+ app: ${job.namePrefix}
495
+ spec:
496
+ restartPolicy: ${job.restartPolicy}
497
+ ${nodeName ? ` nodeName: ${nodeName}\n` : ''} containers:
498
+ - name: ${job.namePrefix}
499
+ image: ${image}
500
+ workingDir: ${job.workingDirectory}
501
+ command: ['sh', '-lc', '${command}']
502
+ env:
503
+ - name: NODE_ENV
504
+ value: test
505
+ - name: ${UNDERPOST_TESTING.allureResultsEnvKey}
506
+ value: ${allure.resultsPath}
507
+ volumeMounts:
508
+ - name: results
509
+ mountPath: ${allure.resultsPath}
510
+ volumes:
511
+ - name: results
512
+ persistentVolumeClaim:
513
+ claimName: ${allure.pvcName}`;
514
+ };
515
+
516
+ export {
517
+ UNDERPOST_TESTING,
518
+ TEST_TIERS,
519
+ allureManifestsFactory,
520
+ coverageIncludeFactory,
521
+ coverageThresholdFactory,
522
+ resolveTestSelection,
523
+ resolveTestTiers,
524
+ testJobManifestFactory,
525
+ testProjectsFactory,
526
+ testSuiteNames,
527
+ vitestArgsFactory,
528
+ };