@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
@@ -0,0 +1,73 @@
1
+ 'use strict';
2
+
3
+ import shell from 'shelljs';
4
+
5
+ /**
6
+ * Deterministic stand-in for the host commands `shellExec` shells out to.
7
+ *
8
+ * `shellExec` resolves `shell.exec` off the shelljs module object on every call,
9
+ * so replacing that one property reaches every caller — the CLI entrypoints, the
10
+ * nftables statics, the WireGuard sync steps — without any of them taking an
11
+ * injection seam they do not otherwise need.
12
+ *
13
+ * @module test/support/shell-harness.js
14
+ */
15
+
16
+ /**
17
+ * Builds a shelljs `ShellString`-shaped result.
18
+ *
19
+ * `shellExec` branches on `.code` and returns either `.stdout` or the object
20
+ * itself, and callers that skip `{ stdout: true }` interpolate the result
21
+ * directly — so the object has to stringify to its stdout the way shelljs does.
22
+ */
23
+ const shellResult = ({ code = 0, stdout = '', stderr = '' } = {}) => ({
24
+ code,
25
+ stdout,
26
+ stderr,
27
+ toString: () => stdout,
28
+ });
29
+
30
+ const matches = (command, match) => {
31
+ if (typeof match === 'function') return match(command);
32
+ if (match instanceof RegExp) return match.test(command);
33
+ return `${command}`.includes(match);
34
+ };
35
+
36
+ /**
37
+ * Installs the `shell.exec` stub for one test.
38
+ *
39
+ * @param {object[]} [routes] - `{ match, code, stdout, stderr, throws }` in
40
+ * priority order; the first whose `match` (substring, RegExp or predicate)
41
+ * hits decides the result. Unmatched commands succeed with empty output.
42
+ * @param {object} [options]
43
+ * @param {object} [options.fallback] - Result for a command no route matched.
44
+ * @returns {{calls: string[], ran: Function, count: Function, route: Function, restore: Function}}
45
+ */
46
+ const shellHarness = (routes = [], { fallback = {} } = {}) => {
47
+ const calls = [];
48
+ const table = [...routes];
49
+
50
+ const spy = vi.spyOn(shell, 'exec').mockImplementation((command, _options, callback) => {
51
+ calls.push(command);
52
+ const route = table.find((entry) => matches(command, entry.match));
53
+ if (route?.throws) throw route.throws instanceof Error ? route.throws : new Error(`${route.throws}`);
54
+ const result = shellResult(route ?? fallback);
55
+ // shelljs hands the async path `(code, stdout, stderr)`; `shellExec` returns
56
+ // whatever `shell.exec` returned without inspecting it in that mode.
57
+ if (typeof callback === 'function') callback(result.code, result.stdout, result.stderr);
58
+ return result;
59
+ });
60
+
61
+ return {
62
+ calls,
63
+ /** Whether any command matched. */
64
+ ran: (match) => calls.some((command) => matches(command, match)),
65
+ /** How many commands matched. */
66
+ count: (match) => calls.filter((command) => matches(command, match)).length,
67
+ /** Adds a route ahead of the existing ones, for a mid-test change of host state. */
68
+ route: (entry) => table.unshift(entry),
69
+ restore: () => spy.mockRestore(),
70
+ };
71
+ };
72
+
73
+ export { shellHarness, shellResult };
@@ -0,0 +1,97 @@
1
+ 'use strict';
2
+
3
+ import { execSync } from 'node:child_process';
4
+ import os from 'node:os';
5
+
6
+ import { expect } from 'chai';
7
+ import fs from 'fs-extra';
8
+
9
+ import { DefaultConf } from '../../conf.js';
10
+ import {
11
+ ensureTemplateCheckout,
12
+ gitOriginRepositoryName,
13
+ pruneTemplateWorkTree,
14
+ validateTemplatePath,
15
+ } from '../../src/server/runtime/conf.js';
16
+ import { TEMPLATE_PRESERVED_ENTRIES } from '../../src/projects/underpost/catalog-underpost.js';
17
+
18
+ const gitCheckout = (originUrl) => {
19
+ const path = fs.mkdtempSync(`${os.tmpdir()}/underpost-template-`);
20
+ execSync('git init -q', { cwd: path });
21
+ if (originUrl) execSync(`git remote add origin ${originUrl}`, { cwd: path });
22
+ return path;
23
+ };
24
+
25
+ describe('template checkout guard', () => {
26
+ const created = [];
27
+ const checkout = (originUrl) => {
28
+ const path = gitCheckout(originUrl);
29
+ created.push(path);
30
+ return path;
31
+ };
32
+
33
+ afterAll(() => created.forEach((path) => fs.removeSync(path)));
34
+
35
+ it('accepts a checkout whose origin is the template repository', () => {
36
+ const path = checkout('https://github.com/underpostnet/pwa-microservices-template.git');
37
+ expect(ensureTemplateCheckout({ toPath: path, githubUsername: 'underpostnet', noClone: true })).to.equal(false);
38
+ });
39
+
40
+ it('rejects a checkout carrying another repository history', () => {
41
+ // Publishing a deploy id swaps the checkout `.git` for its product repo, and
42
+ // an assembly that trusted it would read that product's package.json identity
43
+ // back into the base template.
44
+ const path = checkout('https://github.com/underpostnet/engine-test-cyberia.git');
45
+ expect(() => ensureTemplateCheckout({ toPath: path, githubUsername: 'underpostnet', noClone: true })).to.throw(
46
+ 'not a underpostnet/pwa-microservices-template checkout',
47
+ );
48
+ });
49
+
50
+ it('reports no origin for a checkout that declares none and for a plain directory', () => {
51
+ expect(gitOriginRepositoryName(checkout())).to.equal(null);
52
+ const plain = fs.mkdtempSync(`${os.tmpdir()}/underpost-plain-`);
53
+ created.push(plain);
54
+ expect(gitOriginRepositoryName(plain)).to.equal(null);
55
+ });
56
+ });
57
+
58
+ describe('template work tree prune', () => {
59
+ it('keeps only the entries a rebuild cannot reconstruct', () => {
60
+ const path = fs.mkdtempSync(`${os.tmpdir()}/underpost-prune-`);
61
+ fs.outputFileSync(`${path}/.git/HEAD`, 'ref: refs/heads/master\n');
62
+ fs.outputFileSync(`${path}/node_modules/underpost/index.js`, '');
63
+ fs.outputFileSync(`${path}/src/client/components/core/RenamedAway.js`, '');
64
+ fs.outputFileSync(`${path}/package.json`, '{}');
65
+
66
+ pruneTemplateWorkTree(path, TEMPLATE_PRESERVED_ENTRIES);
67
+
68
+ expect(fs.readdirSync(path).sort()).to.deep.equal(['.git', 'node_modules']);
69
+ fs.removeSync(path);
70
+ });
71
+ });
72
+
73
+ // The filter resolves the base template against the default host and client that only
74
+ // the engine's conf declares; a product build ships its own deploy conf instead.
75
+ const defaultHostConf = DefaultConf.server?.['default.net']?.['/'];
76
+ const describeBaseTemplate = describe.skipIf(!defaultHostConf?.apis?.length || !DefaultConf.client?.default?.services);
77
+
78
+ describeBaseTemplate('template path selection', () => {
79
+ // A skipped suite still runs its body at collection time, so nothing here may dereference
80
+ // a conf the product build does not ship.
81
+ const apis = defaultHostConf?.apis ?? [];
82
+
83
+ it('carries the api entrypoint that sits next to the api directory', () => {
84
+ // `src/api.js` is a documented development entrypoint, not one of the API
85
+ // modules the deploy conf selects between.
86
+ expect(validateTemplatePath('.//src/api.js')).to.equal(true);
87
+ });
88
+
89
+ it('carries the api modules the conf declares, and the shared types', () => {
90
+ for (const api of apis) expect(validateTemplatePath(`.//src/api/${api}/${api}.service.js`), api).to.equal(true);
91
+ expect(validateTemplatePath('.//src/api/types.js')).to.equal(true);
92
+ });
93
+
94
+ it('drops an api module the conf does not declare', () => {
95
+ expect(validateTemplatePath('.//src/api/not-a-declared-api/not-a-declared-api.service.js')).to.equal(false);
96
+ });
97
+ });
@@ -0,0 +1,132 @@
1
+ 'use strict';
2
+
3
+ import { expect } from 'chai';
4
+ import { execFileSync } from 'node:child_process';
5
+ import fs from 'fs-extra';
6
+ import { EXECUTION_PROFILE_ENV_KEY, withExecutionProfile } from '../../src/server/build/execution.js';
7
+ import { shellExec } from '../../src/server/runtime/process.js';
8
+
9
+ const sourceUrl = (relative) => new URL(`../../${relative}`, import.meta.url);
10
+ const readSource = (relative) => fs.readFileSync(sourceUrl(relative), 'utf8');
11
+ const hasSource = (relative) => fs.existsSync(sourceUrl(relative));
12
+
13
+ // A product build strips the CLIs it does not own, so an absent product entrypoint
14
+ // is a CLI this tree does not ship, not a failure.
15
+ const CYBERIA_CLI = 'bin/cyberia.js';
16
+
17
+ describe('shellExec enforces the active execution profile', () => {
18
+ const originalProfile = process.env[EXECUTION_PROFILE_ENV_KEY];
19
+
20
+ afterEach(() => {
21
+ if (originalProfile === undefined) delete process.env[EXECUTION_PROFILE_ENV_KEY];
22
+ else process.env[EXECUTION_PROFILE_ENV_KEY] = originalProfile;
23
+ });
24
+
25
+ it('runs local build work under HERMETIC_BUILD', () => {
26
+ withExecutionProfile('HERMETIC_BUILD', () => {
27
+ expect(`${shellExec('echo hermetic', { stdout: true, silent: true, disableLog: true })}`.trim()).to.equal(
28
+ 'hermetic',
29
+ );
30
+ });
31
+ });
32
+
33
+ it('elides a cluster write and reports success rather than throwing', () => {
34
+ withExecutionProfile('HERMETIC_BUILD', () => {
35
+ // The gate must not look like a failure: the manifest build calls this on a box with
36
+ // no apiserver, and a throw here is exactly the breakage the profile exists to remove.
37
+ const result = shellExec('kubectl delete secret underpost-config -n default --ignore-not-found');
38
+ expect(result.code).to.equal(0);
39
+ expect(result.stderr).to.equal('');
40
+ });
41
+ });
42
+
43
+ it('answers an elided cluster read with the empty result callers already handle', () => {
44
+ withExecutionProfile('HERMETIC_BUILD', () => {
45
+ expect(shellExec('kubectl get svc x -n default', { stdout: true })).to.equal('');
46
+ expect(`${shellExec('kubectl get svc x -n default')}`).to.equal('');
47
+ });
48
+ });
49
+
50
+ it('runs the same cluster command under LIVE_CLUSTER', () => {
51
+ withExecutionProfile('LIVE_CLUSTER', () => {
52
+ // Reaches the shell; without a cluster it exits non-zero, which is the live contract.
53
+ const result = shellExec('kubectl get svc definitely-absent -n default', {
54
+ silentOnError: true,
55
+ silent: true,
56
+ disableLog: true,
57
+ });
58
+ expect(result.code).to.not.equal(0);
59
+ });
60
+ });
61
+ });
62
+
63
+ describe('e2e-build runs without a cluster', () => {
64
+ const runSource = readSource('src/cli/run.js');
65
+ const runner = runSource.slice(
66
+ runSource.indexOf(`'build-cluster-deployment-manifests':`),
67
+ runSource.indexOf('@method monitor-ui'),
68
+ );
69
+
70
+ it('declares HERMETIC_BUILD instead of appending bypass flags', () => {
71
+ expect(runner).to.include(`withExecutionProfile('HERMETIC_BUILD'`);
72
+ expect(runner).to.not.include('--disable-update-underpost-config');
73
+ });
74
+
75
+ it('still builds both environments through the resolved CLI', () => {
76
+ const deployCommands = runner.match(/\$\{underpost\} deploy [^`]*/g) ?? [];
77
+ expect(deployCommands).to.have.lengthOf(2);
78
+ expect(runner).to.include('dd development');
79
+ expect(runner).to.include('dd production --cert');
80
+ });
81
+
82
+ it('re-enters this checkout rather than any globally installed underpost', () => {
83
+ // Regression: auto-resolution prefers a global install, which on a root shell runs a
84
+ // different package against this repo's cwd — it failed on a missing dd.router.
85
+ expect(runner).to.include(`cli('underpost', { local: true })`);
86
+ expect(runner).to.not.match(/\bcli\(\)/);
87
+ });
88
+ });
89
+
90
+ describe('binary resolution is centralized', () => {
91
+ it('leaves no hand-rolled underpost/node-bin branch behind', () => {
92
+ for (const file of ['src/cli/run.js', 'src/cli/db.js', 'src/cli/monitor.js']) {
93
+ expect(readSource(file), file).to.not.include(`'node bin' : 'underpost'`);
94
+ }
95
+ });
96
+
97
+ it('re-enters the executing package from every multi-stage runner', () => {
98
+ // Regression: `run dev-cluster` resolved to whatever underpost was globally installed.
99
+ // A stale one looked for credential seeds under engine-private/ after this version moved
100
+ // them to engine-private/deploy/, so MongoDB bootstrapped with empty root credentials and
101
+ // died on "not authorized". A re-entrant stage must run the code its parent runs.
102
+ for (const file of ['src/cli/run.js', 'src/cli/monitor.js']) {
103
+ const source = readSource(file);
104
+ expect(source, file).to.not.match(/cli\('underpost',\s*\{\s*local:\s*options\.dev/);
105
+ expect(source, file).to.not.match(/\bcli\(\)/);
106
+ }
107
+ });
108
+
109
+ it.skipIf(!hasSource(CYBERIA_CLI))('never shells out to a bare global underpost from the cyberia CLI', () => {
110
+ const shelledOut = readSource(CYBERIA_CLI).match(
111
+ /(?<!\$\{cli\(\)\} )\bunderpost (?=clone|pull|push|cmt|run|start|deploy|secret)/g,
112
+ );
113
+ expect(shelledOut, `unresolved underpost invocations: ${shelledOut}`).to.equal(null);
114
+ });
115
+
116
+ it('replaces a checkout without depending on what that checkout installed', () => {
117
+ // Regression: the pre-pull clean ran through the global `underpost`, which is linked at
118
+ // the very tree being replaced — a node left without dependencies failed the pull that
119
+ // would have repaired it, and the fresh checkout was then used uninstalled.
120
+ const source = readSource('src/cli/run.js');
121
+ const runner = source.slice(source.indexOf(' pull: (path'), source.indexOf(`'ssh-deploy':`));
122
+ expect(runner).to.not.match(/shellExec\(`underpost /);
123
+ expect(runner).to.include('Underpost.repo.clean(');
124
+ expect(runner).to.include('npm install');
125
+ });
126
+
127
+ it('exposes the profile as one root-level flag rather than per-command bypasses', () => {
128
+ const cliSource = readSource('src/cli/index.js');
129
+ expect(cliSource).to.include(`program.option(\n '--profile <profile>'`);
130
+ expect(cliSource).to.include(`program.hook('preAction'`);
131
+ });
132
+ });
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ import { expect } from 'chai';
4
+ import fs from 'fs-extra';
5
+ import { EMPTY_CATALOG, loadProductCatalogs } from '../../src/server/build/catalog.js';
6
+ import { TEST_TIERS } from '../../src/server/build/testing.js';
7
+
8
+ // A broken catalog path fails during template assembly, long after the commit
9
+ // that broke it, so the tree is asserted here instead.
10
+ //
11
+ // A base template has had every product stripped out, including the catalogs
12
+ // that describe the strip — there is nothing left to assert against, and the
13
+ // paths these check are the ones it legitimately no longer carries.
14
+ const catalogs = await loadProductCatalogs();
15
+ const describeProducts = describe.skipIf(catalogs.length === 0);
16
+
17
+ describeProducts('product catalogs', () => {
18
+ it('every catalog carries the uniform shape', () => {
19
+ for (const catalog of catalogs)
20
+ for (const key of Object.keys(EMPTY_CATALOG)) expect(catalog, key).to.have.property(key);
21
+ });
22
+
23
+ it('every engine path packaged into a product CLI exists', () => {
24
+ for (const { templatePaths } of catalogs)
25
+ for (const path of templatePaths) expect(fs.existsSync(`.${path}`), path).to.equal(true);
26
+ });
27
+
28
+ it('every path stripped from the base template exists', () => {
29
+ for (const { stripPaths } of catalogs)
30
+ for (const path of stripPaths) expect(fs.existsSync(path), path).to.equal(true);
31
+ });
32
+
33
+ it('every moved or copied source exists', () => {
34
+ // `sourceMoves` alone are exempt: they read from private sibling repos that
35
+ // are an external input and are not expected to be checked out here.
36
+ for (const { moves, copies } of catalogs)
37
+ for (const [source] of [...moves, ...copies]) expect(fs.existsSync(source), source).to.equal(true);
38
+ });
39
+
40
+ it('resolves paths against the roots the build actually uses', () => {
41
+ // `templatePaths` are copied as `.${path}`, `stripPaths` as `${toPath}/${path}`.
42
+ for (const { templatePaths, stripPaths } of catalogs) {
43
+ for (const path of templatePaths) expect(path, path).to.match(/^\//);
44
+ for (const path of stripPaths) expect(path, path).to.match(/^\.\//);
45
+ }
46
+ });
47
+ });
48
+
49
+ describeProducts('product catalogs and the test tiers', () => {
50
+ // A tier a product strips from the base template but does not ship is a tier
51
+ // nothing runs: the template keeps no tests for the code it removed, and the
52
+ // product CLI arrives without the suite that covers what it added.
53
+ const strippedTiers = TEST_TIERS.filter(({ directory }) =>
54
+ catalogs.some(({ stripPaths }) => stripPaths.includes(`./${directory}`)),
55
+ );
56
+
57
+ it('has products that own at least one tier', () => {
58
+ expect(strippedTiers).to.not.be.empty;
59
+ });
60
+
61
+ it('gives every tier a directory that exists in an unsliced tree', () => {
62
+ for (const { name, directory } of TEST_TIERS) expect(fs.existsSync(directory), name).to.equal(true);
63
+ });
64
+
65
+ it('ships every tier it strips from the base template', () => {
66
+ for (const { name, directory } of strippedTiers) {
67
+ const owner = catalogs.find(({ stripPaths }) => stripPaths.includes(`./${directory}`));
68
+ expect(owner.templatePaths, name).to.include(`/${directory}`);
69
+ }
70
+ });
71
+ });