@underpostnet/cyberia 3.3.0 → 3.3.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +17 -5
  3. package/.github/workflows/coverall.cyberia.ci.yml +39 -14
  4. package/.github/workflows/cyberia-client.cd.yml +5 -0
  5. package/.github/workflows/cyberia-server.cd.yml +5 -0
  6. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  7. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  8. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  9. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  10. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  11. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  12. package/.github/workflows/engine-cyberia.cd.yml +3 -0
  13. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  14. package/.github/workflows/ghpkg.ci.yml +35 -20
  15. package/.github/workflows/hardhat.ci.yml +12 -11
  16. package/.github/workflows/npmpkg.ci.yml +17 -15
  17. package/.github/workflows/publish.cyberia.ci.yml +44 -0
  18. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  19. package/.github/workflows/release.cd.yml +1 -0
  20. package/.prettierignore +1 -0
  21. package/AGENTS.md +96 -0
  22. package/CHANGELOG.md +653 -2513
  23. package/CLI-HELP.md +323 -157
  24. package/Dockerfile +25 -9
  25. package/Dockerfile.dev +25 -9
  26. package/Dockerfile.test +5 -5
  27. package/README.md +48 -28
  28. package/bin/build.js +86 -41
  29. package/bin/build.template.js +8 -3
  30. package/bin/cyberia.js +1494 -1403
  31. package/bin/deploy.js +18 -104
  32. package/bin/index.js +1494 -1403
  33. package/compose.env +17 -5
  34. package/conf.js +98 -7
  35. package/deploy/cyberia-client/deploy.sh +46 -0
  36. package/deploy/cyberia-client/package.sh +17 -0
  37. package/deploy/cyberia-client/state.sh +15 -0
  38. package/deploy/cyberia-server/deploy.sh +46 -0
  39. package/deploy/cyberia-server/package.sh +17 -0
  40. package/deploy/cyberia-server/state.sh +15 -0
  41. package/deploy/dd-cyberia/deploy.sh +9 -29
  42. package/deploy/dd-cyberia/init.sh +38 -45
  43. package/deploy/dd-cyberia/package.sh +16 -0
  44. package/deploy/dd-cyberia/state.sh +14 -0
  45. package/deploy/dd-cyberia/sync-deploy.sh +133 -147
  46. package/deploy/lib/config.sh +29 -0
  47. package/deploy/lib/github-actions-logging.sh +610 -0
  48. package/deploy/lib/host.sh +194 -0
  49. package/deploy/lib/state.sh +65 -0
  50. package/deploy/pwa-microservices-template/deploy.sh +17 -42
  51. package/deploy/release/deploy.sh +9 -41
  52. package/deployment.yaml +7 -2
  53. package/docker-compose.yml +23 -17
  54. package/examples/static-page/README.md +19 -19
  55. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  56. package/hardhat/hardhat.config.js +1 -6
  57. package/hardhat/package-lock.json +101 -40
  58. package/hardhat/package.json +2 -2
  59. package/manifests/alertmanager/deployment.yaml +81 -0
  60. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  61. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
  62. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
  63. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  64. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  65. package/manifests/deployment/mongo-express/deployment.yaml +46 -27
  66. package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
  67. package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
  68. package/manifests/deployment/mongo-express/service.yaml +16 -0
  69. package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
  70. package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
  71. package/manifests/grafana/deployment.yaml +26 -7
  72. package/manifests/grafana/kustomization.yaml +1 -0
  73. package/manifests/grafana/service.yaml +6 -1
  74. package/manifests/mariadb/pv.yaml +1 -0
  75. package/manifests/mongodb/statefulset.yaml +9 -2
  76. package/manifests/mysql/pv-pvc.yaml +14 -1
  77. package/manifests/postgresql/pv.yaml +12 -1
  78. package/manifests/postgresql/pvc.yaml +1 -0
  79. package/manifests/prometheus/deployment.yaml +18 -22
  80. package/package.json +87 -12
  81. package/scripts/event-monitor.sh +56 -0
  82. package/scripts/k3s-node-setup.sh +27 -14
  83. package/scripts/kubeadm-node-setup.sh +31 -11
  84. package/scripts/maas-setup.sh +8 -8
  85. package/scripts/selinux-normalize.sh +907 -0
  86. package/scripts/shutdown-machine.sh +843 -0
  87. package/scripts/test-monitor.sh +5 -5
  88. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +15 -10
  89. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
  90. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +7 -2
  91. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +90 -186
  92. package/src/api/core/core.controller.js +1 -1
  93. package/src/api/core/core.router.js +2 -2
  94. package/src/api/core/core.service.js +2 -2
  95. package/src/api/crypto/crypto.controller.js +1 -1
  96. package/src/api/crypto/crypto.service.js +1 -1
  97. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  98. package/src/api/cyberia-action/cyberia-action.router.js +3 -3
  99. package/src/api/cyberia-action/cyberia-action.service.js +5 -6
  100. package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
  101. package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
  102. package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
  103. package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
  104. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +2 -4
  105. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
  106. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +13 -35
  107. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +17 -34
  108. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  109. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
  110. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
  111. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  112. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  113. package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
  114. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  115. package/src/api/cyberia-entity/cyberia-entity.service.js +3 -3
  116. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
  117. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
  118. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -2
  119. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +468 -5
  120. package/src/api/cyberia-instance/cyberia-fallback-capture.js +502 -0
  121. package/src/api/cyberia-instance/cyberia-fallback-world.js +29 -40
  122. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
  123. package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
  124. package/src/api/cyberia-instance/cyberia-instance-map.service.js +35 -142
  125. package/src/api/cyberia-instance/cyberia-instance.controller.js +2 -5
  126. package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
  127. package/src/api/cyberia-instance/cyberia-instance.router.js +5 -18
  128. package/src/api/cyberia-instance/cyberia-instance.service.js +5 -45
  129. package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
  130. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  131. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
  132. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  133. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +76 -3
  134. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  135. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  136. package/src/api/cyberia-map/cyberia-map.service.js +8 -4
  137. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
  138. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
  139. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
  140. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
  141. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  142. package/src/api/cyberia-quest/cyberia-quest.router.js +4 -4
  143. package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
  144. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  145. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
  146. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  147. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  148. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  149. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  150. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  151. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -214
  152. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  153. package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
  154. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  155. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  156. package/src/api/default/default.controller.js +1 -1
  157. package/src/api/default/default.router.js +1 -1
  158. package/src/api/default/default.service.js +2 -2
  159. package/src/api/document/document.controller.js +1 -1
  160. package/src/api/document/document.router.js +1 -1
  161. package/src/api/document/document.service.js +2 -2
  162. package/src/api/file/file.controller.js +1 -1
  163. package/src/api/file/file.ref.js +153 -0
  164. package/src/api/file/file.ref.json +11 -2
  165. package/src/api/file/file.router.js +1 -1
  166. package/src/api/file/file.service.js +2 -2
  167. package/src/api/instance/instance.controller.js +1 -1
  168. package/src/api/instance/instance.router.js +1 -1
  169. package/src/api/instance/instance.service.js +2 -2
  170. package/src/api/ipfs/ipfs.controller.js +1 -1
  171. package/src/api/ipfs/ipfs.router.js +2 -2
  172. package/src/api/ipfs/ipfs.service.js +2 -2
  173. package/src/api/object-layer/object-layer.controller.js +1 -1
  174. package/src/api/object-layer/object-layer.model.js +47 -12
  175. package/src/api/object-layer/object-layer.router.js +12 -5
  176. package/src/api/object-layer/object-layer.service.js +116 -123
  177. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  178. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  179. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  180. package/src/api/test/test.controller.js +1 -1
  181. package/src/api/test/test.service.js +1 -1
  182. package/src/api/user/guest.service.js +3 -3
  183. package/src/api/user/user.controller.js +1 -1
  184. package/src/api/user/user.router.js +2 -2
  185. package/src/api/user/user.service.js +4 -4
  186. package/src/api.js +5 -9
  187. package/src/cli/app.js +402 -0
  188. package/src/cli/baremetal.js +30 -35
  189. package/src/cli/client.js +306 -0
  190. package/src/cli/cloud-init.js +3 -3
  191. package/src/cli/cluster.js +191 -82
  192. package/src/cli/db.js +120 -68
  193. package/src/cli/deploy.js +157 -75
  194. package/src/cli/docker-compose.js +5 -5
  195. package/src/cli/domains.js +184 -0
  196. package/src/cli/dotenv-store.js +143 -0
  197. package/src/cli/event.js +2281 -0
  198. package/src/cli/fs-selection.js +115 -0
  199. package/src/cli/fs.js +159 -343
  200. package/src/cli/host.js +672 -0
  201. package/src/cli/image.js +4 -6
  202. package/src/cli/index.js +343 -151
  203. package/src/cli/ipfs.js +34 -30
  204. package/src/cli/kickstart.js +1 -1
  205. package/src/cli/kubectl.js +218 -41
  206. package/src/cli/lxd.js +3 -3
  207. package/src/cli/monitor.js +1359 -26
  208. package/src/cli/package.js +90 -0
  209. package/src/cli/release.js +16 -12
  210. package/src/cli/repository.js +586 -363
  211. package/src/cli/run.js +398 -843
  212. package/src/cli/secrets.js +2158 -964
  213. package/src/cli/ssh.js +478 -279
  214. package/src/cli/state.js +394 -0
  215. package/src/cli/static.js +2 -2
  216. package/src/cli/system.js +1 -1
  217. package/src/cli/test.js +203 -125
  218. package/src/cli/vultr.js +61 -21
  219. package/src/cli/wireguard.js +1112 -306
  220. package/src/client/components/core/CalendarCore.js +53 -96
  221. package/src/client/components/core/Docs.js +327 -303
  222. package/src/client/components/core/FileExplorer.js +0 -21
  223. package/src/client/components/core/Modal.js +56 -1
  224. package/src/client/components/core/PanelForm.js +4 -4
  225. package/src/client/components/core/Repository.js +56 -0
  226. package/src/client/components/core/Translate.js +7 -0
  227. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  228. package/src/client/components/core/Wallet.js +0 -11
  229. package/src/client/components/core/Worker.js +7 -1
  230. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  231. package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
  232. package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
  233. package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
  234. package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
  235. package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
  236. package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
  237. package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
  238. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
  239. package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
  240. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -35
  241. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
  242. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
  243. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  244. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
  245. package/src/client/components/default/AppShellDefault.js +1 -1
  246. package/src/client/components/default/SettingsDefault.js +2 -2
  247. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  248. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  249. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  250. package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
  251. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +313 -30
  252. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
  253. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
  254. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
  255. package/src/client/public/cyberia-docs/CYBERIA.md +48 -28
  256. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
  257. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  258. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  259. package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
  260. package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
  261. package/src/client/public/default/android-chrome-144x144.png +0 -0
  262. package/src/client/public/default/android-chrome-192x192.png +0 -0
  263. package/src/client/public/default/android-chrome-256x256.png +0 -0
  264. package/src/client/public/default/android-chrome-36x36.png +0 -0
  265. package/src/client/public/default/android-chrome-384x384.png +0 -0
  266. package/src/client/public/default/android-chrome-48x48.png +0 -0
  267. package/src/client/public/default/android-chrome-512x512.png +0 -0
  268. package/src/client/public/default/android-chrome-72x72.png +0 -0
  269. package/src/client/public/default/android-chrome-96x96.png +0 -0
  270. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  271. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  272. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  273. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  274. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  275. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  276. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  277. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  278. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  279. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  280. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  281. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  282. package/src/client/public/default/apple-touch-icon.png +0 -0
  283. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  284. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  285. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  286. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  287. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  288. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  289. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  290. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  291. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  292. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  293. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  294. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  295. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  296. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  297. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  298. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  299. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  300. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  301. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  302. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  303. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  304. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  305. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  306. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  307. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  308. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  309. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  310. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  311. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  312. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  313. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  314. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  315. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  316. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  317. package/src/client/public/default/assets/background/white.jpg +0 -0
  318. package/src/client/public/default/browserconfig.xml +1 -1
  319. package/src/client/public/default/favicon-16x16.png +0 -0
  320. package/src/client/public/default/favicon-32x32.png +0 -0
  321. package/src/client/public/default/favicon-48x48.png +0 -0
  322. package/src/client/public/default/favicon.ico +0 -0
  323. package/src/client/public/default/manifest.webmanifest +5 -5
  324. package/src/client/public/default/mstile-144x144.png +0 -0
  325. package/src/client/public/default/mstile-150x150.png +0 -0
  326. package/src/client/public/default/mstile-310x150.png +0 -0
  327. package/src/client/public/default/mstile-310x310.png +0 -0
  328. package/src/client/public/default/mstile-70x70.png +0 -0
  329. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  330. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  331. package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
  332. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
  333. package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
  334. package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
  335. package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
  336. package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
  337. package/src/client/services/object-layer/object-layer.management.js +6 -10
  338. package/src/client/services/object-layer/object-layer.service.js +3 -1
  339. package/src/client/ssr/RootDocument.js +1 -1
  340. package/src/client/ssr/body/404.js +1 -1
  341. package/src/client/ssr/body/500.js +1 -1
  342. package/src/client/ssr/body/CacheControl.js +1 -1
  343. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  344. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  345. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  346. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  347. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  348. package/src/client/ssr/head/Css.js +1 -1
  349. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  350. package/src/client/ssr/head/DefaultScripts.js +1 -1
  351. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  352. package/src/client/ssr/head/Microdata.js +1 -1
  353. package/src/client/ssr/head/Production.js +1 -1
  354. package/src/client/ssr/head/Pwa.js +1 -1
  355. package/src/client/ssr/head/PwaItemledger.js +1 -1
  356. package/src/client/ssr/head/Seo.js +1 -1
  357. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  358. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  359. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  360. package/src/client/ssr/views/Cyberia404.js +7 -5
  361. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  362. package/src/client/ssr/views/Maintenance.js +1 -1
  363. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  364. package/src/client/ssr/views/Test.js +1 -1
  365. package/src/client/sw/core.sw.js +20 -14
  366. package/src/client-builder/client-build-docs.js +92 -77
  367. package/src/client-builder/client-build-live.js +2 -2
  368. package/src/client-builder/client-build.js +105 -74
  369. package/src/client-builder/client-bundle.js +347 -0
  370. package/src/client-builder/client-dev-server.js +3 -3
  371. package/src/client-builder/client-icons.js +2 -2
  372. package/src/client-builder/ssr.js +3 -3
  373. package/src/client.build.js +3 -6
  374. package/src/client.dev.js +3 -6
  375. package/src/db/DataBaseProvider.js +186 -3
  376. package/src/db/mariadb/MariaDB.js +3 -2
  377. package/src/db/mongo/MongoBootstrap.js +273 -101
  378. package/src/db/mongo/MongoExpress.js +187 -0
  379. package/src/db/mongo/MongooseDB.js +7 -8
  380. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  381. package/src/grpc/cyberia/grpc-server.js +6 -8
  382. package/src/index.js +79 -23
  383. package/src/mailer/EmailRender.js +2 -2
  384. package/src/mailer/MailerInterceptor.js +87 -0
  385. package/src/mailer/MailerProvider.js +50 -6
  386. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +144 -147
  387. package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
  388. package/src/projects/cyberia/besu-genesis-generator.js +8 -17
  389. package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
  390. package/src/projects/cyberia/catalog-cyberia.js +54 -10
  391. package/src/projects/cyberia/gemini-client.js +4 -4
  392. package/src/projects/cyberia/generate-saga.js +5 -12
  393. package/src/projects/cyberia/hot-reload-trigger.js +18 -29
  394. package/src/projects/cyberia/instance-backup.js +210 -0
  395. package/src/projects/cyberia/instance-data.js +178 -258
  396. package/src/projects/cyberia/ipfs-client.js +4 -4
  397. package/src/projects/cyberia/map-preview-generator.js +33 -69
  398. package/src/projects/cyberia/object-layer.js +153 -320
  399. package/src/projects/cyberia/seed-audio.js +139 -0
  400. package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
  401. package/src/projects/cyberia/semantic-layer-generator.js +3 -19
  402. package/src/projects/cyberia/stat-balance.js +81 -0
  403. package/src/projects/cyberia/stat-commands.js +23 -0
  404. package/src/projects/cyberia/stat-contract-generator.js +101 -0
  405. package/src/projects/underpost/catalog-underpost.js +9 -1
  406. package/src/proxy.js +4 -7
  407. package/src/runtime/cyberia-client/Dockerfile +17 -8
  408. package/src/runtime/cyberia-client/Dockerfile.dev +13 -4
  409. package/src/runtime/cyberia-server/Dockerfile +18 -6
  410. package/src/runtime/cyberia-server/Dockerfile.dev +16 -3
  411. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  412. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  413. package/src/runtime/engine-cyberia/Dockerfile.test +5 -5
  414. package/src/runtime/engine-cyberia/compose.env +17 -5
  415. package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
  416. package/src/runtime/express/Express.js +32 -27
  417. package/src/runtime/lampp/Lampp.js +22 -70
  418. package/src/runtime/nginx/Nginx.js +1 -1
  419. package/src/runtime/wp/Wp.js +16 -48
  420. package/src/server/{catalog.js → build/catalog.js} +15 -5
  421. package/src/server/build/coverage.js +188 -0
  422. package/src/server/build/execution.js +402 -0
  423. package/src/server/build/package.js +508 -0
  424. package/src/server/build/testing.js +578 -0
  425. package/src/server/{dns.js → network/dns.js} +144 -11
  426. package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
  427. package/src/server/{middlewares.js → network/middlewares.js} +11 -5
  428. package/src/server/network/node-capability.js +98 -0
  429. package/src/server/{peer.js → network/peer.js} +3 -3
  430. package/src/server/{proxy.js → network/proxy.js} +7 -13
  431. package/src/server/network/router.js +356 -0
  432. package/src/server/{tls.js → network/tls.js} +2 -2
  433. package/src/server/{underpost-compression.js → network/underpost-compression.js} +1 -1
  434. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
  435. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
  436. package/src/server/{cri.js → ops/cri.js} +2 -2
  437. package/src/server/{cron.js → ops/cron.js} +349 -74
  438. package/src/server/ops/event-notification.js +284 -0
  439. package/src/server/{logger.js → ops/logger.js} +143 -23
  440. package/src/server/ops/monitoring.js +1724 -0
  441. package/src/server/{systemd.js → ops/systemd.js} +55 -1
  442. package/src/server/{conf.js → runtime/conf.js} +516 -423
  443. package/src/server/runtime/config-scope.js +215 -0
  444. package/src/server/runtime/environment.js +149 -0
  445. package/src/server/{process.js → runtime/process.js} +153 -12
  446. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  447. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  448. package/src/server/{start.js → runtime/start.js} +128 -39
  449. package/src/server/{auth.js → security/auth.js} +7 -8
  450. package/src/server/security/container-storage.js +382 -0
  451. package/src/server/{crypto.js → security/crypto.js} +1 -1
  452. package/src/server/{selinux.js → security/selinux.js} +1 -1
  453. package/src/server/{backup.js → storage/backup.js} +17 -8
  454. package/src/server/{data-query.js → storage/data-query.js} +17 -1
  455. package/src/server/storage/downloader.js +121 -0
  456. package/src/server/storage/repository.js +68 -0
  457. package/src/server/storage/zip.js +153 -0
  458. package/src/server.js +4 -7
  459. package/src/ws/IoInterface.js +1 -1
  460. package/src/ws/IoServer.js +1 -1
  461. package/src/ws/core/core.ws.connection.js +1 -1
  462. package/src/ws/core/core.ws.emit.js +1 -1
  463. package/src/ws/core/core.ws.server.js +1 -1
  464. package/src/ws/default/default.ws.connection.js +1 -1
  465. package/src/ws/default/default.ws.emit.js +1 -1
  466. package/src/ws/default/default.ws.server.js +1 -1
  467. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  468. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  469. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  470. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  471. package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
  472. package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
  473. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +64 -0
  474. package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
  475. package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
  476. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +17 -23
  477. package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
  478. package/test/integration/app/cyberia/cyberia-load.test.js +466 -0
  479. package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
  480. package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
  481. package/test/integration/app/cyberia/fallback-world-capture.test.js +338 -0
  482. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  483. package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
  484. package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
  485. package/test/integration/app/cyberia/seed-audio.test.js +275 -0
  486. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  487. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  488. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  489. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  490. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  491. package/test/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
  492. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  493. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  494. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  495. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  496. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  497. package/test/integration/infra/2-network/wireguard-cli.test.js +1187 -0
  498. package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +649 -55
  499. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  500. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  501. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  502. package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
  503. package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
  504. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  505. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  506. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  507. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +6 -6
  508. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -4
  509. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  510. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  511. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  512. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  513. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  514. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  515. package/test/support/shell-harness.js +73 -0
  516. package/test/unit/build-template.test.js +97 -0
  517. package/test/unit/build-workflow-offline.test.js +132 -0
  518. package/test/unit/catalog.test.js +71 -0
  519. package/test/unit/client-build-docs.test.js +361 -0
  520. package/test/unit/client-bundle.test.js +313 -0
  521. package/test/unit/conf-loading.test.js +303 -0
  522. package/test/unit/conf-resolution.test.js +996 -0
  523. package/test/unit/coverage-artifact.test.js +221 -0
  524. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  525. package/test/unit/cyberia/instance-backup.test.js +183 -0
  526. package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
  527. package/test/unit/cyberia/publish-workflow.test.js +22 -0
  528. package/test/unit/cyberia/stat-balance.test.js +69 -0
  529. package/test/unit/deploy-env-resolution.test.js +38 -0
  530. package/test/unit/deploy-log-table.test.js +518 -0
  531. package/test/unit/downloader-integrity.test.js +98 -0
  532. package/test/unit/execution-profiles.test.js +219 -0
  533. package/test/unit/file-reference-registry.test.js +141 -0
  534. package/test/unit/fleet-sync-source.test.js +149 -0
  535. package/test/unit/fs-storage-paths.test.js +596 -0
  536. package/test/unit/logger-redaction.test.js +141 -0
  537. package/test/unit/package.test.js +457 -0
  538. package/test/unit/prepare-host.test.js +382 -0
  539. package/test/unit/process-environment.test.js +18 -0
  540. package/test/unit/propagation-message.test.js +78 -0
  541. package/test/unit/redeploy-plan.test.js +24 -0
  542. package/test/unit/release-bump.test.js +474 -0
  543. package/test/unit/ssh-output-redaction.test.js +28 -0
  544. package/test/unit/start-options.test.js +46 -0
  545. package/test/unit/test-tiers.test.js +220 -0
  546. package/test/unit/zip-archive.test.js +142 -0
  547. package/vitest.config.js +66 -0
  548. package/.nycrc +0 -9
  549. package/deploy/lib/logging.sh +0 -96
  550. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  551. package/manifests/mongodb/pv-pvc.yaml +0 -59
  552. package/scripts/coverall-test-cyberia.sh +0 -24
  553. package/scripts/coverall-test.sh +0 -24
  554. package/scripts/link-local-underpost-cli.sh +0 -6
  555. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
  556. package/src/api/user/user.build.js +0 -16
  557. package/src/cli/env.js +0 -177
  558. package/src/client/components/core/Blockchain.js +0 -41
  559. package/src/client/components/core/Blog.js +0 -9
  560. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  561. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
  562. package/src/client/public/default/assets/background/dark.jpg +0 -0
  563. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  564. package/src/client/public/default/assets/background/white0.jpg +0 -0
  565. package/src/client/public/doc/favicon.ico +0 -0
  566. package/src/client/public/doc/sitemap +0 -148
  567. package/src/server/downloader.js +0 -73
  568. package/src/server/environment.js +0 -98
@@ -11,17 +11,22 @@
11
11
  */
12
12
 
13
13
  import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
14
- import { loggerFactory } from '../../server/logger.js';
14
+ import { loggerFactory } from '../../server/ops/logger.js';
15
15
  import { ObjectLayerRenderFramesDto } from '../object-layer-render-frames/object-layer-render-frames.model.js';
16
16
  import { FileFactory } from '../file/file.service.js';
17
17
  import fs from 'fs-extra';
18
+ import os from 'node:os';
19
+ import path from 'node:path';
20
+ import sharp from 'sharp';
21
+ import { validateStats } from '../../client/components/cyberia/SharedDefaultsCyberia.js';
18
22
  import { ObjectLayerDto } from './object-layer.model.js';
19
23
  import { ObjectLayerEngine } from '../../projects/cyberia/object-layer.js';
20
- import { shellExec } from '../../server/process.js';
21
- import { DataQuery } from '../../server/data-query.js';
24
+ import { shellExec } from '../../server/runtime/process.js';
25
+ import { DataQuery } from '../../server/storage/data-query.js';
22
26
  import { AtlasSpriteSheetService } from '../atlas-sprite-sheet/atlas-sprite-sheet.service.js';
27
+ import { AtlasSpriteSheetStore } from '../../projects/cyberia/atlas-sprite-sheet-store.js';
23
28
  import { IpfsClient } from '../../projects/cyberia/ipfs-client.js';
24
- import { createPinRecord, removePinRecordsAndUnpin } from '../ipfs/ipfs.service.js';
29
+ import { removePinRecordsAndUnpin } from '../ipfs/ipfs.service.js';
25
30
 
26
31
  /**
27
32
  * Logger instance for this module.
@@ -45,8 +50,8 @@ class ObjectLayerService {
45
50
  * - `/metadata/:itemType/:itemId` — Create an object layer from uploaded frames and metadata.
46
51
  * - Default — Create an object layer directly from the request body.
47
52
  *
48
- * The `/metadata` and default routes delegate to {@link ObjectLayerEngine.createObjectLayerDocuments}
49
- * for document creation, atlas generation, SHA-256 computation, and IPFS pinning.
53
+ * The `/metadata` and default routes delegate to {@link ObjectLayerEngine.persistObjectLayerDocuments}
54
+ * for the document write, atlas generation, SHA-256 computation, and IPFS pinning.
50
55
  *
51
56
  * @async
52
57
  * @function post
@@ -160,22 +165,12 @@ class ObjectLayerService {
160
165
  metadataOverride: req.body,
161
166
  });
162
167
 
163
- const { objectLayer } = await ObjectLayerEngine.createObjectLayerDocuments({
168
+ const { objectLayer } = await ObjectLayerEngine.persistObjectLayerDocuments({
164
169
  ObjectLayer,
165
170
  ObjectLayerRenderFrames,
166
171
  objectLayerRenderFramesData,
167
172
  objectLayerData,
168
- createOptions: {
169
- generateAtlas: true,
170
- atlasServiceContext: {
171
- req,
172
- res,
173
- options,
174
- AtlasSpriteSheetService,
175
- IpfsClient,
176
- createPinRecord,
177
- },
178
- },
173
+ persistOptions: { options },
179
174
  });
180
175
 
181
176
  return objectLayer;
@@ -191,44 +186,32 @@ class ObjectLayerService {
191
186
  bodyData.data.render.cid = '';
192
187
  bodyData.data.render.metadataCid = '';
193
188
 
194
- // If has render frames, generate atlas + CIDs BEFORE creating the ObjectLayer
189
+ // Stage the atlas CIDs before the write, so the document is never stored without them.
195
190
  if (bodyData.objectLayerRenderFramesId) {
196
191
  const renderFramesDoc = await ObjectLayerRenderFrames.findById(bodyData.objectLayerRenderFramesId);
197
192
  if (renderFramesDoc) {
198
193
  try {
199
- const stagingOL = {
200
- data: bodyData.data,
201
- objectLayerRenderFramesId: renderFramesDoc,
202
- };
203
- const result = await AtlasSpriteSheetService.generate(
204
- { objectLayer: stagingOL, auth: req.auth },
205
- res,
194
+ const { atlasDoc, atlasCid, atlasMetadataCid } = await AtlasSpriteSheetStore.persist({
195
+ itemKey: bodyData.data.item.id,
196
+ objectLayerRenderFrames: renderFramesDoc,
206
197
  options,
207
- { skipObjectLayerSave: true },
208
- );
209
- bodyData.data.render.cid = result.atlasCid;
210
- bodyData.data.render.metadataCid = result.atlasMetadataCid;
211
- bodyData.atlasSpriteSheetId = result.atlasDoc._id;
198
+ });
199
+ bodyData.data.render.cid = atlasCid;
200
+ bodyData.data.render.metadataCid = atlasMetadataCid;
201
+ bodyData.atlasSpriteSheetId = atlasDoc._id;
212
202
  } catch (atlasError) {
213
203
  logger.error('Failed to auto-generate atlas for new ObjectLayer:', atlasError);
214
204
  }
215
205
  }
216
206
  }
217
207
 
218
- // Pin data JSON to IPFS
219
- try {
220
- const itemId = bodyData.data.item.id;
221
- const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
222
- const ipfsResult = await IpfsClient.addJsonToIpfs(bodyData.data, `${itemId}_data.json`, mfsPath);
223
- if (ipfsResult) {
224
- bodyData.cid = ipfsResult.cid;
225
- await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
226
- }
227
- } catch (ipfsError) {
228
- logger.warn('Failed to pin data JSON to IPFS:', ipfsError.message);
229
- }
208
+ const dataCid = await ObjectLayerEngine.pinObjectLayerData({
209
+ data: bodyData.data,
210
+ itemId: bodyData.data.item.id,
211
+ options,
212
+ });
213
+ if (dataCid) bodyData.cid = dataCid;
230
214
 
231
- // Atomic create/replace – ObjectLayer is fully populated with all CIDs
232
215
  return await (await ObjectLayer.upsertByItemId(bodyData)).populate('objectLayerRenderFramesId');
233
216
  };
234
217
 
@@ -257,25 +240,33 @@ class ObjectLayerService {
257
240
  /** @type {import('./object-layer.model.js').ObjectLayerModel} */
258
241
  const ObjectLayer = DataBaseProviderService.getModel('ObjectLayer', options);
259
242
 
260
- // GET /search-item-ids?q=<partial> - Fast partial match search on data.item.id
243
+ // Object layers are addressed by item id, the key the editor navigates by.
244
+ const keyFilter = (key) => DataQuery.naturalKeyFilter('data.item.id', key);
245
+
246
+ // GET /search-item-ids - item identity, by prefix (`q`, for type-ahead) or by exact ids
247
+ // (`ids`, comma separated). Carries the item's type because that is what addresses its
248
+ // sprite directory; an id alone cannot be previewed.
261
249
  if (req.path.startsWith('/search-item-ids')) {
262
250
  const q = (req.query.q || '').trim();
263
- if (!q) return { itemIds: [] };
264
- // Escape regex special characters for safe partial matching
265
- const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
266
- const results = await ObjectLayer.find(
267
- { 'data.item.id': { $regex: escaped, $options: 'i' } },
268
- { 'data.item.id': 1, _id: 0 },
269
- )
270
- .limit(20)
251
+ const ids = String(req.query.ids || '')
252
+ .split(',')
253
+ .map((id) => id.trim())
254
+ .filter(Boolean);
255
+ if (!q && ids.length === 0) return { items: [] };
256
+ const query = ids.length
257
+ ? { 'data.item.id': { $in: ids } }
258
+ : // Escape regex special characters for safe partial matching
259
+ { 'data.item.id': { $regex: q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), $options: 'i' } };
260
+ const results = await ObjectLayer.find(query, { 'data.item.id': 1, 'data.item.type': 1, _id: 0 })
261
+ .limit(ids.length ? ids.length : 20)
271
262
  .lean();
272
- const itemIds = [...new Set(results.map((r) => r.data.item.id))];
273
- return { itemIds };
263
+ const byId = new Map(results.map((r) => [r.data.item.id, r.data.item.type || '']));
264
+ return { items: [...byId].map(([id, type]) => ({ id, type })) };
274
265
  }
275
266
 
276
267
  // GET /frame-counts/:id - Get frame counts for each direction using numeric codes
277
268
  if (req.path.startsWith('/frame-counts/')) {
278
- const objectLayer = await ObjectLayer.findById(req.params.id)
269
+ const objectLayer = await ObjectLayer.findOne(keyFilter(req.params.id))
279
270
  .select(ObjectLayerDto.select.getMetadata())
280
271
  .populate('objectLayerRenderFramesId');
281
272
  if (!objectLayer) {
@@ -318,7 +309,7 @@ class ObjectLayerService {
318
309
 
319
310
  // GET /render/:id - Get only render data for specific object layer
320
311
  if (req.path.startsWith('/render/')) {
321
- const objectLayer = await ObjectLayer.findById(req.params.id)
312
+ const objectLayer = await ObjectLayer.findOne(keyFilter(req.params.id))
322
313
  .select(ObjectLayerDto.select.getRender())
323
314
  .populate('objectLayerRenderFramesId');
324
315
  if (!objectLayer) {
@@ -333,7 +324,7 @@ class ObjectLayerService {
333
324
 
334
325
  // GET /metadata/:id - Get only metadata (no render frames/colors) for specific object layer
335
326
  if (req.path.startsWith('/metadata/')) {
336
- const objectLayer = await ObjectLayer.findById(req.params.id)
327
+ const objectLayer = await ObjectLayer.findOne(keyFilter(req.params.id))
337
328
  .select(ObjectLayerDto.select.getMetadata())
338
329
  .populate('objectLayerRenderFramesId', ObjectLayerRenderFramesDto.select.get());
339
330
  if (!objectLayer) {
@@ -385,22 +376,14 @@ class ObjectLayerService {
385
376
  }
386
377
 
387
378
  // GET / - Get paginated list of object layers
388
- const id = req.params.id || req.query.id;
389
- logger.info(`ObjectLayerService.get - filtering check - id: ${id}`);
390
- if (id && id !== 'undefined' && !['render', 'metadata', 'frame-counts'].includes(id)) {
391
- try {
392
- const objectLayer = await ObjectLayer.findById(id)
393
- .select(ObjectLayerDto.select.get())
394
- .populate('atlasSpriteSheetId', 'cid')
395
- .populate('objectLayerRenderFramesId', ObjectLayerRenderFramesDto.select.get());
396
- if (objectLayer) {
397
- logger.info(`ObjectLayerService.get - found record by id: ${id}`);
398
- return { data: [objectLayer], total: 1, page: 1, totalPages: 1 };
399
- }
400
- logger.warn(`ObjectLayerService.get - record NOT found for id: ${id}`);
401
- } catch (e) {
402
- logger.warn(`Invalid ID format or not found: ${id}`);
403
- }
379
+ const key = req.params.id || req.query.id;
380
+ if (key && key !== 'undefined' && !['render', 'metadata', 'frame-counts'].includes(key)) {
381
+ const objectLayer = await ObjectLayer.findOne(keyFilter(key))
382
+ .select(ObjectLayerDto.select.get())
383
+ .populate('atlasSpriteSheetId', 'cid')
384
+ .populate('objectLayerRenderFramesId', ObjectLayerRenderFramesDto.select.get());
385
+ if (objectLayer) return { data: [objectLayer], total: 1, page: 1, totalPages: 1 };
386
+ logger.warn(`ObjectLayerService.get - no object layer for key: ${key}`);
404
387
  }
405
388
 
406
389
  const { query, sort, skip, limit, page } = DataQuery.parse(req.query);
@@ -493,9 +476,14 @@ class ObjectLayerService {
493
476
  // Create temporary output file path
494
477
  const tempOutputPath = `${framesFolder}/${tmpOutputFileName}`;
495
478
 
479
+ // img2webp takes one frame size, and frames of one direction may differ: the game
480
+ // stretches each to the entity's cell box, so the preview stretches them to the
481
+ // largest one — nearest-neighbour, since a scaled frame is still pixel art.
482
+ const stagedFolder = await ObjectLayerService.stageUniformFrames(framesFolder, pngFiles);
483
+
496
484
  try {
497
485
  // Change to the frames directory and execute img2webp command
498
- const cmd = `cd "${framesFolder}" && img2webp -d ${frameDuration} -loop 0 *.png -o ${tmpOutputFileName}`;
486
+ const cmd = `cd "${stagedFolder ?? framesFolder}" && img2webp -d ${frameDuration} -loop 0 *.png -o "${path.resolve(tempOutputPath)}"`;
499
487
 
500
488
  logger.info(`Executing command: ${cmd}`);
501
489
 
@@ -546,9 +534,41 @@ class ObjectLayerService {
546
534
  }
547
535
 
548
536
  throw error;
537
+ } finally {
538
+ if (stagedFolder) await fs.remove(stagedFolder);
549
539
  }
550
540
  };
551
541
 
542
+ /**
543
+ * Stages copies of the frames resized to one common size when they differ, or returns null
544
+ * when they already share one and can be encoded in place.
545
+ * @function stageUniformFrames
546
+ * @memberof ObjectLayerService
547
+ * @param {string} framesFolder - Directory holding the direction's PNG frames.
548
+ * @param {string[]} pngFiles - Frame file names, in animation order.
549
+ * @returns {Promise<string|null>} Temporary directory with the resized frames, or null.
550
+ */
551
+ static stageUniformFrames = async (framesFolder, pngFiles) => {
552
+ const sizes = await Promise.all(
553
+ pngFiles.map(async (file) => {
554
+ const { width, height } = await sharp(`${framesFolder}/${file}`).metadata();
555
+ return { file, width, height };
556
+ }),
557
+ );
558
+ const width = Math.max(...sizes.map((size) => size.width));
559
+ const height = Math.max(...sizes.map((size) => size.height));
560
+ if (sizes.every((size) => size.width === width && size.height === height)) return null;
561
+
562
+ const stagedFolder = await fs.mkdtemp(path.join(os.tmpdir(), 'ol-webp-'));
563
+ for (const { file } of sizes) {
564
+ await sharp(`${framesFolder}/${file}`)
565
+ .resize(width, height, { fit: 'fill', kernel: 'nearest' })
566
+ .toFile(`${stagedFolder}/${file}`);
567
+ }
568
+ logger.info(`Staged ${pngFiles.length} frame(s) at ${width}x${height} for webp encoding`);
569
+ return stagedFolder;
570
+ };
571
+
552
572
  /**
553
573
  * PUT handler for updating object layers, their frame images, and metadata.
554
574
  *
@@ -557,8 +577,8 @@ class ObjectLayerService {
557
577
  * - `/:id/metadata/:itemType/:itemId` — Update metadata and reprocess all frames.
558
578
  * - `/:id` — Standard update from request body.
559
579
  *
560
- * The `/metadata` route delegates to {@link ObjectLayerEngine.updateObjectLayerDocuments}
561
- * for document update, atlas regeneration, SHA-256 computation, and IPFS pinning.
580
+ * The `/metadata` route delegates to {@link ObjectLayerEngine.persistObjectLayerDocuments}
581
+ * for the document write, atlas regeneration, SHA-256 computation, and IPFS pinning.
562
582
  *
563
583
  * @async
564
584
  * @function put
@@ -652,7 +672,6 @@ class ObjectLayerService {
652
672
 
653
673
  // PUT /:id/metadata/:itemType/:itemId - Update object layer metadata and reprocess all frames
654
674
  if (req.path.includes('/metadata/')) {
655
- const objectLayerId = req.params.id;
656
675
  const itemType = req.params.itemType;
657
676
  const itemId = req.params.itemId;
658
677
 
@@ -683,24 +702,12 @@ class ObjectLayerService {
683
702
  metadataOverride: req.body,
684
703
  });
685
704
 
686
- // Update documents using engine method (with atlas generation)
687
- const { objectLayer } = await ObjectLayerEngine.updateObjectLayerDocuments({
688
- objectLayerId,
705
+ const { objectLayer } = await ObjectLayerEngine.persistObjectLayerDocuments({
689
706
  ObjectLayer,
690
707
  ObjectLayerRenderFrames,
691
708
  objectLayerRenderFramesData,
692
709
  objectLayerData,
693
- updateOptions: {
694
- generateAtlas: true,
695
- atlasServiceContext: {
696
- req,
697
- res,
698
- options,
699
- AtlasSpriteSheetService,
700
- IpfsClient,
701
- createPinRecord,
702
- },
703
- },
710
+ persistOptions: { options },
704
711
  });
705
712
 
706
713
  return objectLayer;
@@ -715,25 +722,19 @@ class ObjectLayerService {
715
722
  // Apply body updates to staging data in memory
716
723
  const updateData = { ...req.body };
717
724
  const stagingData = updateData.data || existingOL.data.toObject();
725
+ stagingData.stats = validateStats(stagingData.stats);
718
726
  if (!stagingData.render) stagingData.render = {};
719
727
 
720
- // Use existing render frames if available
721
- const renderFramesData = existingOL.objectLayerRenderFramesId;
722
- if (renderFramesData) {
728
+ if (existingOL.objectLayerRenderFramesId) {
723
729
  try {
724
- const stagingOL = {
725
- data: stagingData,
726
- objectLayerRenderFramesId: renderFramesData,
727
- };
728
- const result = await AtlasSpriteSheetService.generate(
729
- { objectLayer: stagingOL, auth: req.auth },
730
- res,
730
+ const { atlasDoc, atlasCid, atlasMetadataCid } = await AtlasSpriteSheetStore.persist({
731
+ itemKey: stagingData.item.id,
732
+ objectLayerRenderFrames: existingOL.objectLayerRenderFramesId,
731
733
  options,
732
- { skipObjectLayerSave: true },
733
- );
734
- stagingData.render.cid = result.atlasCid;
735
- stagingData.render.metadataCid = result.atlasMetadataCid;
736
- updateData.atlasSpriteSheetId = result.atlasDoc._id;
734
+ });
735
+ stagingData.render.cid = atlasCid;
736
+ stagingData.render.metadataCid = atlasMetadataCid;
737
+ updateData.atlasSpriteSheetId = atlasDoc._id;
737
738
  } catch (atlasError) {
738
739
  logger.error('Failed to auto-update atlas for ObjectLayer:', atlasError);
739
740
  }
@@ -742,25 +743,17 @@ class ObjectLayerService {
742
743
  updateData.data = stagingData;
743
744
  updateData.sha256 = ObjectLayerEngine.computeSha256(stagingData);
744
745
 
745
- // Pin data JSON to IPFS
746
- try {
747
- const itemId = stagingData.item.id;
748
- const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
749
- const ipfsResult = await IpfsClient.addJsonToIpfs(stagingData, `${itemId}_data.json`, mfsPath);
750
- if (ipfsResult) {
751
- updateData.cid = ipfsResult.cid;
752
- await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
753
- }
754
- } catch (ipfsError) {
755
- logger.warn('Failed to pin data JSON to IPFS:', ipfsError.message);
756
- }
746
+ const dataCid = await ObjectLayerEngine.pinObjectLayerData({
747
+ data: stagingData,
748
+ itemId: stagingData.item.id,
749
+ options,
750
+ });
751
+ if (dataCid) updateData.cid = dataCid;
757
752
 
758
- // Atomic update with all CIDs populated
759
- let updatedObjectLayer = await ObjectLayer.findByIdAndUpdate(req.params.id, updateData, {
753
+ return await ObjectLayer.findByIdAndUpdate(req.params.id, updateData, {
760
754
  returnDocument: 'after',
755
+ runValidators: true,
761
756
  }).populate('objectLayerRenderFramesId');
762
-
763
- return updatedObjectLayer;
764
757
  };
765
758
 
766
759
  /**
@@ -1,4 +1,4 @@
1
- import { buildCrudController } from '../../server/middlewares.js';
1
+ import { buildCrudController } from '../../server/network/middlewares.js';
2
2
  import { ObjectLayerRenderFramesService } from './object-layer-render-frames.service.js';
3
3
 
4
4
  const ObjectLayerRenderFramesController = buildCrudController(ObjectLayerRenderFramesService);
@@ -1,5 +1,5 @@
1
1
  import express from 'express';
2
- import { registerCrudRoutes } from '../../server/middlewares.js';
2
+ import { registerCrudRoutes } from '../../server/network/middlewares.js';
3
3
  import { ObjectLayerRenderFramesController } from './object-layer-render-frames.controller.js';
4
4
 
5
5
  class ObjectLayerRenderFramesRouter {
@@ -1,6 +1,6 @@
1
1
  import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
2
- import { loggerFactory } from '../../server/logger.js';
3
- import { DataQuery } from '../../server/data-query.js';
2
+ import { loggerFactory } from '../../server/ops/logger.js';
3
+ import { DataQuery } from '../../server/storage/data-query.js';
4
4
 
5
5
  const logger = loggerFactory(import.meta);
6
6
 
@@ -1,4 +1,4 @@
1
- import { controllerHandler, sendSuccess, serviceHandler } from '../../server/middlewares.js';
1
+ import { controllerHandler, sendSuccess, serviceHandler } from '../../server/network/middlewares.js';
2
2
  import { TestService } from './test.service.js';
3
3
 
4
4
  class TestController {
@@ -1,5 +1,5 @@
1
1
  import validator from 'validator';
2
- import { loggerFactory } from '../../server/logger.js';
2
+ import { loggerFactory } from '../../server/ops/logger.js';
3
3
  import { TestModel } from './test.model.js';
4
4
  import { getYouTubeID, validatePassword } from '../../client/components/core/CommonJs.js';
5
5
 
@@ -1,7 +1,7 @@
1
1
  import mongoose from 'mongoose';
2
2
  import { UserDto } from './user.model.js';
3
- import { ValkeyAPI } from '../../server/valkey.js';
4
- import { hashPassword, getBearerToken, jwtSign } from '../../server/auth.js';
3
+ import { ValkeyAPI } from '../../db/valkey/Valkey.js';
4
+ import { hashPassword, getBearerToken, jwtSign } from '../../server/security/auth.js';
5
5
 
6
6
  // ─── TTL ──────────────────────────────────────────────────────────────────────
7
7
 
@@ -15,7 +15,7 @@ const _guestTtlMs = () => {
15
15
  /**
16
16
  * Constructs a new ephemeral guest user object.
17
17
  * This is domain logic specific to the guest lifecycle; it does not belong
18
- * in the generic Valkey storage module.
18
+ * in the Valkey database adapter.
19
19
  *
20
20
  * @param {{ host?: string }} options
21
21
  * @returns {object}
@@ -1,4 +1,4 @@
1
- import { loggerFactory } from '../../server/logger.js';
1
+ import { loggerFactory } from '../../server/ops/logger.js';
2
2
  import { UserService } from './user.service.js';
3
3
 
4
4
  const logger = loggerFactory(import.meta);
@@ -1,6 +1,6 @@
1
- import { hashPassword } from '../../server/auth.js';
1
+ import { hashPassword } from '../../server/security/auth.js';
2
2
  import fs from 'fs-extra';
3
- import { loggerFactory } from '../../server/logger.js';
3
+ import { loggerFactory } from '../../server/ops/logger.js';
4
4
  import { UserController } from './user.controller.js';
5
5
  import express from 'express';
6
6
  import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
@@ -7,8 +7,8 @@
7
7
  * @namespace UserService
8
8
  */
9
9
 
10
- import { loggerFactory } from '../../server/logger.js';
11
- import { DataQuery } from '../../server/data-query.js';
10
+ import { loggerFactory } from '../../server/ops/logger.js';
11
+ import { DataQuery } from '../../server/storage/data-query.js';
12
12
  import {
13
13
  hashPassword,
14
14
  verifyPassword,
@@ -19,7 +19,7 @@ import {
19
19
  logoutSession,
20
20
  jwtSign,
21
21
  validatePasswordMiddleware,
22
- } from '../../server/auth.js';
22
+ } from '../../server/security/auth.js';
23
23
  import { MailerProvider } from '../../mailer/MailerProvider.js';
24
24
  import { CoreWsEmitter } from '../../ws/core/core.ws.emit.js';
25
25
  import { CoreWsMailerChannel } from '../../ws/core/channels/core.ws.mailer.js';
@@ -29,7 +29,7 @@ import { FileFactory, FileCleanup } from '../file/file.service.js';
29
29
  import { UserDto } from './user.model.js';
30
30
  import { timer } from '../../client/components/core/CommonJs.js';
31
31
  import { GuestService } from './guest.service.js';
32
- import { resolveHostKeyContext } from '../../server/conf.js';
32
+ import { resolveHostKeyContext } from '../../server/runtime/conf.js';
33
33
 
34
34
  const logger = loggerFactory(import.meta);
35
35
 
package/src/api.js CHANGED
@@ -1,18 +1,14 @@
1
1
  'use strict';
2
2
 
3
- // https://nodejs.org/api
4
- // https://expressjs.com/en/4x/api.html
5
-
6
3
  import dotenv from 'dotenv';
7
- import { loggerFactory } from './server/logger.js';
8
- import { buildClient } from './server/client-build.js';
9
- import { buildRuntime } from './server/runtime.js';
10
- import { ProcessController } from './server/process.js';
11
- import { Config } from './server/conf.js';
4
+ import { loggerFactory } from './server/ops/logger.js';
5
+ import { buildRuntime } from './server/runtime/runtime.js';
6
+ import { ProcessController } from './server/runtime/process.js';
7
+ import { Config, buildApiConf } from './server/runtime/conf.js';
12
8
 
13
9
  dotenv.config();
14
10
 
15
- await Config.build();
11
+ await Config.build(undefined, undefined, await buildApiConf());
16
12
 
17
13
  const logger = loggerFactory(import.meta);
18
14