@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.
- package/.dockerignore +1 -0
- package/.env.example +16 -0
- package/.github/workflows/coverall.cyberia.ci.yml +107 -0
- package/.github/workflows/cyberia-client.cd.yml +6 -18
- package/.github/workflows/cyberia-server.cd.yml +6 -18
- package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
- package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
- package/.github/workflows/engine-cyberia.cd.yml +6 -78
- package/.github/workflows/engine-cyberia.ci.yml +4 -5
- package/.github/workflows/ghpkg.ci.yml +42 -21
- package/.github/workflows/hardhat.ci.yml +12 -11
- package/.github/workflows/npmpkg.ci.yml +17 -15
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
- package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
- package/.github/workflows/release.cd.yml +2 -9
- package/.prettierignore +1 -0
- package/AGENTS.md +47 -0
- package/CHANGELOG.md +581 -2417
- package/CLI-HELP.md +416 -127
- package/Dockerfile +25 -9
- package/Dockerfile.dev +25 -9
- package/Dockerfile.test +4 -4
- package/README.md +21 -1
- package/bin/build.js +70 -43
- package/bin/build.template.js +8 -3
- package/bin/cyberia.js +372 -135
- package/bin/deploy.js +18 -104
- package/bin/index.js +372 -135
- package/compose.env +16 -0
- package/conf.js +93 -4
- package/deploy/cyberia-client/deploy.sh +47 -0
- package/deploy/cyberia-client/package.sh +18 -0
- package/deploy/cyberia-client/state.sh +14 -0
- package/deploy/cyberia-server/deploy.sh +47 -0
- package/deploy/cyberia-server/package.sh +18 -0
- package/deploy/cyberia-server/state.sh +14 -0
- package/deploy/dd-cyberia/deploy.sh +22 -0
- package/deploy/dd-cyberia/init.sh +55 -0
- package/deploy/dd-cyberia/package.sh +17 -0
- package/deploy/dd-cyberia/state.sh +14 -0
- package/deploy/dd-cyberia/sync-deploy.sh +116 -0
- package/deploy/lib/github-actions-logging.sh +594 -0
- package/deploy/lib/host.sh +185 -0
- package/deploy/lib/state.sh +62 -0
- package/deploy/pwa-microservices-template/deploy.sh +45 -0
- package/deploy/release/deploy.sh +32 -0
- package/deployment.yaml +7 -2
- package/docker-compose.yml +31 -37
- package/examples/static-page/README.md +19 -19
- package/examples/static-page/ssr-components/CustomPage.js +2 -2
- package/hardhat/hardhat.config.js +1 -6
- package/hardhat/package-lock.json +104 -43
- package/hardhat/package.json +3 -3
- package/manifests/alertmanager/deployment.yaml +81 -0
- package/manifests/blackbox-exporter/deployment.yaml +75 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +36 -7
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +77 -0
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/grafana/deployment.yaml +26 -7
- package/manifests/grafana/kustomization.yaml +1 -0
- package/manifests/grafana/service.yaml +6 -1
- package/manifests/mariadb/pv.yaml +1 -0
- package/manifests/mongodb/statefulset.yaml +9 -2
- package/manifests/mysql/pv-pvc.yaml +14 -1
- package/manifests/postgresql/pv.yaml +12 -1
- package/manifests/postgresql/pvc.yaml +1 -0
- package/manifests/prometheus/deployment.yaml +18 -22
- package/package.json +83 -10
- package/scripts/audit-selinux.sh +64 -0
- package/scripts/event-monitor.sh +56 -0
- package/scripts/gpu-diag.sh +0 -0
- package/scripts/ip-info.sh +0 -0
- package/scripts/k3s-node-setup.sh +30 -14
- package/scripts/kubeadm-node-setup.sh +40 -31
- package/scripts/lxd-vm-setup.sh +0 -0
- package/scripts/maas-nat-firewalld.sh +0 -0
- package/scripts/maas-setup.sh +8 -8
- package/scripts/nat-iptables.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +0 -0
- package/scripts/rocky-kickstart.sh +25 -9
- package/scripts/selinux-normalize.sh +907 -0
- package/scripts/shutdown-machine.sh +843 -0
- package/scripts/test-monitor.sh +3 -3
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
- package/src/api/core/core.controller.js +1 -1
- package/src/api/core/core.router.js +2 -2
- package/src/api/core/core.service.js +2 -2
- package/src/api/crypto/crypto.controller.js +1 -1
- package/src/api/crypto/crypto.service.js +1 -1
- package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +1 -1
- package/src/api/cyberia-action/cyberia-action.service.js +2 -2
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
- package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
- package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
- package/src/api/cyberia-instance/cyberia-fallback-default-items.js +63 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +16 -1
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
- package/src/api/cyberia-instance/cyberia-instance.controller.js +4 -1
- package/src/api/cyberia-instance/cyberia-instance.router.js +15 -2
- package/src/api/cyberia-instance/cyberia-instance.service.js +45 -2
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +1 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
- package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
- package/src/api/cyberia-map/cyberia-map.router.js +1 -1
- package/src/api/cyberia-map/cyberia-map.service.js +2 -2
- package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
- package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +16 -29
- package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
- package/src/api/default/default.controller.js +1 -1
- package/src/api/default/default.router.js +1 -1
- package/src/api/default/default.service.js +2 -2
- package/src/api/document/document.controller.js +1 -1
- package/src/api/document/document.router.js +1 -1
- package/src/api/document/document.service.js +2 -2
- package/src/api/file/file.controller.js +1 -1
- package/src/api/file/file.router.js +1 -1
- package/src/api/file/file.service.js +2 -2
- package/src/api/instance/instance.controller.js +1 -1
- package/src/api/instance/instance.router.js +1 -1
- package/src/api/instance/instance.service.js +2 -2
- package/src/api/ipfs/ipfs.controller.js +1 -1
- package/src/api/ipfs/ipfs.router.js +2 -2
- package/src/api/ipfs/ipfs.service.js +2 -2
- package/src/api/object-layer/object-layer.controller.js +1 -1
- package/src/api/object-layer/object-layer.model.js +204 -3
- package/src/api/object-layer/object-layer.router.js +2 -2
- package/src/api/object-layer/object-layer.service.js +4 -17
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
- package/src/api/test/test.controller.js +1 -1
- package/src/api/test/test.service.js +1 -1
- package/src/api/user/guest.service.js +3 -3
- package/src/api/user/user.controller.js +1 -1
- package/src/api/user/user.router.js +2 -2
- package/src/api/user/user.service.js +4 -4
- package/src/api.js +5 -9
- package/src/cli/app.js +391 -0
- package/src/cli/baremetal.js +30 -36
- package/src/cli/client.js +306 -0
- package/src/cli/cloud-init.js +3 -3
- package/src/cli/cluster.js +242 -135
- package/src/cli/db.js +126 -67
- package/src/cli/deploy.js +158 -60
- package/src/cli/docker-compose.js +5 -5
- package/src/cli/domains.js +184 -0
- package/src/cli/dotenv-store.js +143 -0
- package/src/cli/event.js +2281 -0
- package/src/cli/fs.js +3 -3
- package/src/cli/host.js +672 -0
- package/src/cli/image.js +4 -7
- package/src/cli/index.js +426 -134
- package/src/cli/ipfs.js +34 -30
- package/src/cli/kickstart.js +1 -1
- package/src/cli/kubectl.js +218 -41
- package/src/cli/lxd.js +3 -3
- package/src/cli/monitor.js +1359 -26
- package/src/cli/package.js +90 -0
- package/src/cli/release.js +73 -34
- package/src/cli/repository.js +564 -367
- package/src/cli/run.js +362 -654
- package/src/cli/secrets.js +2158 -964
- package/src/cli/ssh.js +651 -331
- package/src/cli/state.js +394 -0
- package/src/cli/static.js +2 -2
- package/src/cli/system.js +26 -13
- package/src/cli/test.js +199 -125
- package/src/cli/vultr.js +623 -0
- package/src/cli/wireguard.js +2930 -0
- package/src/client/components/core/CalendarCore.js +53 -96
- package/src/client/components/core/Docs.js +258 -211
- package/src/client/components/core/FileExplorer.js +0 -21
- package/src/client/components/core/PanelForm.js +4 -4
- package/src/client/components/core/Repository.js +56 -0
- package/src/client/components/core/Translate.js +7 -0
- package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
- package/src/client/components/core/Wallet.js +0 -11
- package/src/client/components/core/Worker.js +7 -1
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
- package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +368 -0
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +35 -1
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +4 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppShellDefault.js +1 -1
- package/src/client/components/default/SettingsDefault.js +2 -2
- package/src/client/components/itemledger/SettingsItemledger.js +2 -2
- package/src/client/components/underpost/AppShellUnderpost.js +3 -2
- package/src/client/components/underpost/SettingsUnderpost.js +2 -2
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +17 -3
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +1 -1
- package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-384x384.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-512x512.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
- package/src/client/public/default/assets/background/white.jpg +0 -0
- package/src/client/public/default/browserconfig.xml +1 -1
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon-48x48.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/manifest.webmanifest +5 -5
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/yandex-browser-50x50.png +0 -0
- package/src/client/public/default/yandex-browser-manifest.json +1 -1
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +40 -0
- package/src/client/services/object-layer/object-layer.management.js +4 -4
- package/src/client/ssr/RootDocument.js +1 -1
- package/src/client/ssr/body/404.js +1 -1
- package/src/client/ssr/body/500.js +1 -1
- package/src/client/ssr/body/CacheControl.js +1 -1
- package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
- package/src/client/ssr/head/CryptokoynScripts.js +1 -1
- package/src/client/ssr/head/Css.js +1 -1
- package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +1 -1
- package/src/client/ssr/head/ItemledgerScripts.js +1 -1
- package/src/client/ssr/head/Microdata.js +1 -1
- package/src/client/ssr/head/Production.js +1 -1
- package/src/client/ssr/head/Pwa.js +1 -1
- package/src/client/ssr/head/PwaItemledger.js +1 -1
- package/src/client/ssr/head/Seo.js +1 -1
- package/src/client/ssr/head/UnderpostScripts.js +1 -1
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
- package/src/client/ssr/views/Cyberia404.js +7 -5
- package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/views/Maintenance.js +1 -1
- package/src/client/ssr/views/NoNetworkConnection.js +1 -1
- package/src/client/ssr/views/Test.js +1 -1
- package/src/client/sw/core.sw.js +20 -14
- package/src/client-builder/client-build-docs.js +61 -46
- package/src/client-builder/client-build-live.js +2 -2
- package/src/client-builder/client-build.js +58 -44
- package/src/client-builder/client-dev-server.js +3 -3
- package/src/client-builder/client-icons.js +2 -2
- package/src/client-builder/ssr.js +3 -3
- package/src/client.build.js +3 -6
- package/src/client.dev.js +3 -6
- package/src/db/DataBaseProvider.js +186 -3
- package/src/db/mariadb/MariaDB.js +3 -2
- package/src/db/mongo/MongoBootstrap.js +273 -101
- package/src/db/mongo/MongooseDB.js +11 -8
- package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
- package/src/grpc/cyberia/grpc-server.js +1 -1
- package/src/index.js +103 -23
- package/src/mailer/EmailRender.js +2 -2
- package/src/mailer/MailerInterceptor.js +87 -0
- package/src/mailer/MailerProvider.js +50 -6
- package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
- package/src/projects/cyberia/besu-genesis-generator.js +3 -3
- package/src/projects/cyberia/catalog-cyberia.js +54 -6
- package/src/projects/cyberia/gemini-client.js +1 -1
- package/src/projects/cyberia/generate-saga.js +15 -24
- package/src/projects/cyberia/hot-reload-trigger.js +1 -1
- package/src/projects/cyberia/instance-data.js +22 -3
- package/src/projects/cyberia/ipfs-client.js +4 -4
- package/src/projects/cyberia/map-preview-generator.js +1 -1
- package/src/projects/cyberia/object-layer.js +12 -22
- package/src/projects/cyberia/semantic-layer-generator.js +1 -1
- package/src/projects/underpost/catalog-underpost.js +13 -2
- package/src/proxy.js +4 -7
- package/src/runtime/cyberia-client/Dockerfile +9 -4
- package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
- package/src/runtime/cyberia-server/Dockerfile +9 -4
- package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
- package/src/runtime/engine-cyberia/Dockerfile +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
- package/src/runtime/engine-cyberia/compose.env +16 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +31 -37
- package/src/runtime/express/Express.js +32 -27
- package/src/runtime/lampp/Lampp.js +22 -70
- package/src/runtime/nginx/Nginx.js +1 -1
- package/src/runtime/wp/Wp.js +16 -48
- package/src/server/{catalog.js → build/catalog.js} +15 -5
- package/src/server/build/coverage.js +117 -0
- package/src/server/build/execution.js +402 -0
- package/src/server/build/package.js +465 -0
- package/src/server/build/testing.js +528 -0
- package/src/server/{dns.js → network/dns.js} +241 -14
- package/src/server/network/forward-proxy.js +541 -0
- package/src/server/{middlewares.js → network/middlewares.js} +59 -4
- package/src/server/network/node-capability.js +98 -0
- package/src/server/{peer.js → network/peer.js} +3 -3
- package/src/server/{proxy.js → network/proxy.js} +7 -13
- package/src/server/network/router.js +356 -0
- package/src/server/{tls.js → network/tls.js} +2 -2
- package/src/server/network/underpost-compression.js +186 -0
- package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +26 -16
- package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +19 -3
- package/src/server/{cri.js → ops/cri.js} +2 -2
- package/src/server/ops/cron.js +949 -0
- package/src/server/ops/event-notification.js +284 -0
- package/src/server/{logger.js → ops/logger.js} +108 -23
- package/src/server/ops/monitoring.js +1724 -0
- package/src/server/ops/systemd.js +259 -0
- package/src/server/{conf.js → runtime/conf.js} +521 -520
- package/src/server/runtime/config-scope.js +215 -0
- package/src/server/runtime/environment.js +149 -0
- package/src/server/{process.js → runtime/process.js} +153 -13
- package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
- package/src/server/{runtime.js → runtime/runtime.js} +12 -8
- package/src/server/{start.js → runtime/start.js} +128 -39
- package/src/server/{auth.js → security/auth.js} +7 -8
- package/src/server/security/container-storage.js +382 -0
- package/src/server/{crypto.js → security/crypto.js} +1 -1
- package/src/server/security/selinux.js +185 -0
- package/src/server/{backup.js → storage/backup.js} +17 -8
- package/src/server/{data-query.js → storage/data-query.js} +1 -1
- package/src/server/{downloader.js → storage/downloader.js} +2 -2
- package/src/server/storage/repository.js +68 -0
- package/src/server.js +4 -7
- package/src/ws/IoInterface.js +1 -1
- package/src/ws/IoServer.js +1 -1
- package/src/ws/core/core.ws.connection.js +1 -1
- package/src/ws/core/core.ws.emit.js +1 -1
- package/src/ws/core/core.ws.server.js +1 -1
- package/src/ws/default/default.ws.connection.js +1 -1
- package/src/ws/default/default.ws.emit.js +1 -1
- package/src/ws/default/default.ws.server.js +1 -1
- package/test/e2e/event-e2e-public-ingress-down.js +45 -0
- package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
- package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
- package/test/{api.test.js → integration/app/api.test.js} +33 -14
- package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
- package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +2 -1
- package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
- package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
- package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
- package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
- package/test/integration/infra/1-security/config-scope.test.js +305 -0
- package/test/integration/infra/1-security/container-storage.test.js +356 -0
- package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
- package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
- package/test/integration/infra/1-security/selinux.test.js +69 -0
- package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
- package/test/integration/infra/1-security/systemd-service.test.js +70 -0
- package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
- package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
- package/test/integration/infra/2-network/node-capability.test.js +182 -0
- package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
- package/test/integration/infra/2-network/wireguard-edge.test.js +1731 -0
- package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
- package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
- package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
- package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
- package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
- package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
- package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +47 -6
- package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +56 -4
- package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
- package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
- package/test/integration/infra/5-observability/event-notification.test.js +197 -0
- package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
- package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
- package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
- package/test/support/shell-harness.js +73 -0
- package/test/unit/build-template.test.js +97 -0
- package/test/unit/build-workflow-offline.test.js +132 -0
- package/test/unit/catalog.test.js +71 -0
- package/test/unit/client-build-docs.test.js +334 -0
- package/test/unit/conf-loading.test.js +303 -0
- package/test/unit/conf-resolution.test.js +979 -0
- package/test/unit/coverage-artifact.test.js +130 -0
- package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
- package/test/unit/deploy-env-resolution.test.js +38 -0
- package/test/unit/deploy-log-table.test.js +447 -0
- package/test/unit/execution-profiles.test.js +219 -0
- package/test/unit/fleet-sync-source.test.js +149 -0
- package/test/unit/logger-redaction.test.js +112 -0
- package/test/unit/package.test.js +403 -0
- package/test/unit/prepare-host.test.js +299 -0
- package/test/unit/process-environment.test.js +18 -0
- package/test/unit/propagation-message.test.js +78 -0
- package/test/unit/redeploy-plan.test.js +24 -0
- package/test/unit/release-bump.test.js +474 -0
- package/test/unit/ssh-output-redaction.test.js +28 -0
- package/test/unit/start-options.test.js +46 -0
- package/test/unit/test-tiers.test.js +193 -0
- package/vitest.config.js +58 -0
- package/.nycrc +0 -9
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
- package/manifests/mongodb/pv-pvc.yaml +0 -59
- package/scripts/link-local-underpost-cli.sh +0 -6
- package/src/api/user/user.build.js +0 -16
- package/src/cli/env.js +0 -177
- package/src/client/components/core/Blockchain.js +0 -41
- package/src/client/components/core/Blog.js +0 -9
- package/src/client/components/core/KeyboardAvoidance.js +0 -145
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/white0-min.jpg +0 -0
- package/src/client/public/default/assets/background/white0.jpg +0 -0
- package/src/client/public/doc/favicon.ico +0 -0
- package/src/client/public/doc/sitemap +0 -148
- package/src/server/cron.js +0 -476
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Runtime status contract and the in-pod internal status endpoint
|
|
2
|
+
* Runtime status contract and the in-pod internal status endpoint: the base module of the
|
|
3
|
+
* `state` domain, the runtime monitoring / telemetry layer.
|
|
3
4
|
*
|
|
4
5
|
* Single source of truth for the Underpost runtime readiness signal (Phase 2 of
|
|
5
6
|
* the two-phase deployment monitor). The runtime publishes its lifecycle here;
|
|
@@ -7,23 +8,34 @@
|
|
|
7
8
|
* `kubectl port-forward`. Kubernetes pod readiness (Phase 1) is owned by kubelet
|
|
8
9
|
* and is intentionally not modeled in this module.
|
|
9
10
|
*
|
|
11
|
+
* Three observations make up the layer, and they are deliberately separate:
|
|
12
|
+
* - **execution state** — where the runtime is in its lifecycle (`container-status`)
|
|
13
|
+
* - **health indicators** — whether it is ready and whether it is still booting
|
|
14
|
+
* - **performance metrics** — uptime, memory and CPU of the process serving it
|
|
15
|
+
* {@link runtimeStatusPayload} carries the first for the monitor's failure classification;
|
|
16
|
+
* {@link runtimeTelemetryPayload} carries all three for an agent exporting them off-cluster.
|
|
17
|
+
*
|
|
10
18
|
* Cross-process contract:
|
|
11
|
-
* - In-pod, the canonical value lives in the
|
|
19
|
+
* - In-pod, the canonical value lives in the container state store key
|
|
12
20
|
* `container-status`, written by `start.js`. For non-error phases it carries
|
|
13
21
|
* the namespaced form `<deployId>-<env>-<phase>`; a fatal fault collapses to
|
|
14
22
|
* the bare value `error`.
|
|
15
23
|
* - The internal HTTP server exposes that value (normalized to the bare
|
|
16
24
|
* contract phase) and never exposes secrets, env dumps, or configuration.
|
|
25
|
+
* Neither payload is ever built from `process.env` wholesale — each field is
|
|
26
|
+
* named, so a new environment variable can never widen what is published.
|
|
17
27
|
*
|
|
18
|
-
* @module src/server/runtime-status.js
|
|
28
|
+
* @module src/server/runtime/runtime-status.js
|
|
19
29
|
* @namespace RuntimeStatus
|
|
20
30
|
*/
|
|
21
31
|
|
|
22
32
|
import http from 'node:http';
|
|
33
|
+
import os from 'node:os';
|
|
23
34
|
import fs from 'fs-extra';
|
|
24
35
|
import dotenv from 'dotenv';
|
|
25
|
-
import Underpost from '
|
|
26
|
-
import {
|
|
36
|
+
import Underpost from '../../index.js';
|
|
37
|
+
import { EXECUTION_PROFILES, activeExecutionProfile } from '../build/execution.js';
|
|
38
|
+
import { loggerFactory } from '../ops/logger.js';
|
|
27
39
|
|
|
28
40
|
const logger = loggerFactory(import.meta);
|
|
29
41
|
|
|
@@ -41,9 +53,15 @@ const RUNTIME_STATUS = {
|
|
|
41
53
|
|
|
42
54
|
const CONTAINER_STATUS_KEY = 'container-status';
|
|
43
55
|
const START_CONTAINER_STATUS_KEY = 'start-container-status';
|
|
56
|
+
// The boot latch: present from the moment a runtime starts configuring itself until that runtime
|
|
57
|
+
// is listening. Container-scoped like the two above — same owner, same lifetime — so it lives in
|
|
58
|
+
// the container state store. It was previously written to the host configuration store, where
|
|
59
|
+
// `host load` and `host clean` erase the whole file and would silently drop the latch mid-boot.
|
|
60
|
+
const AWAIT_DEPLOY_KEY = 'await-deploy';
|
|
44
61
|
const INTERNAL_STATUS_PATH = '/_internal/status';
|
|
45
62
|
const INTERNAL_READY_PATH = '/_internal/ready';
|
|
46
63
|
const INTERNAL_HEALTH_PATH = '/_internal/health';
|
|
64
|
+
const INTERNAL_TELEMETRY_PATH = '/_internal/telemetry';
|
|
47
65
|
|
|
48
66
|
/**
|
|
49
67
|
* Resolves the internal status port. Defaults to the deployment base `PORT`
|
|
@@ -117,22 +135,47 @@ const normalizeContainerStatus = (raw) => {
|
|
|
117
135
|
* @returns {string|undefined}
|
|
118
136
|
*/
|
|
119
137
|
const getRuntimeStatus = () =>
|
|
120
|
-
normalizeContainerStatus(Underpost.
|
|
138
|
+
normalizeContainerStatus(Underpost.state.get(CONTAINER_STATUS_KEY, undefined, { disableLog: true }));
|
|
121
139
|
|
|
122
140
|
/**
|
|
123
|
-
* Reads the start-container-status
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* endpoint so K8s pod readiness is never derailed by lifecycle noise.
|
|
141
|
+
* Reads the start-container-status key — an insulated marker the start pipeline writes once
|
|
142
|
+
* after completing the running phase. Unlike container-status, which lifecycle hooks and failure
|
|
143
|
+
* latches also write, this is only ever set by that pipeline, so the readinessProbe endpoint is
|
|
144
|
+
* never derailed by lifecycle noise.
|
|
128
145
|
* @memberof RuntimeStatus
|
|
129
146
|
* @returns {string|undefined}
|
|
130
147
|
*/
|
|
131
148
|
const getStartContainerStatus = () => {
|
|
132
|
-
const raw = Underpost.
|
|
149
|
+
const raw = Underpost.state.get(START_CONTAINER_STATUS_KEY, undefined, { disableLog: true });
|
|
133
150
|
return raw && typeof raw === 'string' && raw.trim() ? raw.trim() : undefined;
|
|
134
151
|
};
|
|
135
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Latches this container as still bringing its runtime up. Cleared by {@link clearAwaitDeploy}
|
|
155
|
+
* once the runtime is listening; polled by `awaitDeployMonitor` in between.
|
|
156
|
+
* @memberof RuntimeStatus
|
|
157
|
+
* @returns {void}
|
|
158
|
+
*/
|
|
159
|
+
const latchAwaitDeploy = () => {
|
|
160
|
+
Underpost.state.set(AWAIT_DEPLOY_KEY, new Date().toISOString());
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Whether a runtime in this container is still coming up.
|
|
165
|
+
* @memberof RuntimeStatus
|
|
166
|
+
* @returns {boolean}
|
|
167
|
+
*/
|
|
168
|
+
const isAwaitingDeploy = () => Boolean(Underpost.state.get(AWAIT_DEPLOY_KEY, undefined, { disableLog: true }));
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Releases the boot latch. Called by the runtime once every configured host and path is bound.
|
|
172
|
+
* @memberof RuntimeStatus
|
|
173
|
+
* @returns {void}
|
|
174
|
+
*/
|
|
175
|
+
const clearAwaitDeploy = () => {
|
|
176
|
+
Underpost.state.delete(AWAIT_DEPLOY_KEY);
|
|
177
|
+
};
|
|
178
|
+
|
|
136
179
|
/**
|
|
137
180
|
* Minimal, secret-free payload served by the internal status endpoint and used
|
|
138
181
|
* by the monitor for failure classification and observability.
|
|
@@ -145,6 +188,43 @@ const runtimeStatusPayload = () => ({
|
|
|
145
188
|
env: process.env.NODE_ENV ?? null,
|
|
146
189
|
});
|
|
147
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Live execution state, health indicators and performance metrics for this container: what a
|
|
193
|
+
* telemetry agent collects and exports off-cluster.
|
|
194
|
+
*
|
|
195
|
+
* A superset of {@link runtimeStatusPayload}, kept separate from it because the monitor's
|
|
196
|
+
* failure classification must not start depending on metrics that move on every read. Every
|
|
197
|
+
* field is named individually and none is read from the environment in bulk, so this can never
|
|
198
|
+
* become an env dump.
|
|
199
|
+
* @memberof RuntimeStatus
|
|
200
|
+
* @returns {object} Secret-free telemetry observation.
|
|
201
|
+
*/
|
|
202
|
+
const runtimeTelemetryPayload = () => {
|
|
203
|
+
const memory = process.memoryUsage();
|
|
204
|
+
const cpu = process.cpuUsage();
|
|
205
|
+
return {
|
|
206
|
+
...runtimeStatusPayload(),
|
|
207
|
+
instanceId: process.env.INSTANCE_ID ?? null,
|
|
208
|
+
health: {
|
|
209
|
+
// The insulated readiness marker, not the lifecycle status: the two disagree exactly when
|
|
210
|
+
// a lifecycle hook has moved container-status after the start pipeline signed off.
|
|
211
|
+
ready: Boolean(getStartContainerStatus()),
|
|
212
|
+
awaitingDeploy: isAwaitingDeploy(),
|
|
213
|
+
inContainer: Underpost.state.isInsideContainer(),
|
|
214
|
+
},
|
|
215
|
+
metrics: {
|
|
216
|
+
uptimeSeconds: Math.round(process.uptime()),
|
|
217
|
+
rssBytes: memory.rss,
|
|
218
|
+
heapUsedBytes: memory.heapUsed,
|
|
219
|
+
heapTotalBytes: memory.heapTotal,
|
|
220
|
+
cpuUserMicros: cpu.user,
|
|
221
|
+
cpuSystemMicros: cpu.system,
|
|
222
|
+
loadAverage1m: os.loadavg()[0],
|
|
223
|
+
},
|
|
224
|
+
observedAt: new Date().toISOString(),
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
|
|
148
228
|
/**
|
|
149
229
|
* Emits a structured, secret-free deployment transition event.
|
|
150
230
|
* @memberof RuntimeStatus
|
|
@@ -167,10 +247,56 @@ const emitRuntimeEvent = ({ deployId, env, phase }) => {
|
|
|
167
247
|
* @param {string} phase - One of {@link RUNTIME_STATUS}.
|
|
168
248
|
*/
|
|
169
249
|
const setRuntimeStatus = (deployId, env, phase) => {
|
|
170
|
-
Underpost.
|
|
250
|
+
Underpost.state.set(CONTAINER_STATUS_KEY, containerStatusValue(deployId, env, phase));
|
|
171
251
|
emitRuntimeEvent({ deployId, env, phase });
|
|
172
252
|
};
|
|
173
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Whether this process is executing under a test runner.
|
|
256
|
+
* @memberof RuntimeStatus
|
|
257
|
+
* @returns {boolean} True under `NODE_ENV=test` or a Vitest worker.
|
|
258
|
+
*/
|
|
259
|
+
const isTestRuntime = () =>
|
|
260
|
+
process.env.NODE_ENV === 'test' || Boolean(process.env.VITEST || process.env.VITEST_WORKER_ID);
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Whether this process may write the runtime status contract.
|
|
264
|
+
*
|
|
265
|
+
* Only a live workload observes itself. A test run and a non-live execution profile both
|
|
266
|
+
* execute commands whose non-zero exit is the expected outcome — a suite asserting a failure
|
|
267
|
+
* path, a hermetic build eliding a cluster call — and neither is an observation of a running
|
|
268
|
+
* deployment. Letting them latch `container-status` published a false `error` to the CD
|
|
269
|
+
* monitor and failed rollouts that were healthy.
|
|
270
|
+
* @memberof RuntimeStatus
|
|
271
|
+
* @returns {boolean} True when this process speaks for a live container.
|
|
272
|
+
*/
|
|
273
|
+
const runtimeStatusWritable = () =>
|
|
274
|
+
Underpost.state.isInsideContainer() &&
|
|
275
|
+
!isTestRuntime() &&
|
|
276
|
+
activeExecutionProfile().name === EXECUTION_PROFILES.LIVE_CLUSTER.name;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Latches the container as failed, for a failure detected outside the lifecycle phases — a shell
|
|
280
|
+
* command, a database connection, a backup. A no-op wherever the contract is not writable:
|
|
281
|
+
* outside a container, under a test runner, or under a non-live execution profile.
|
|
282
|
+
* @memberof RuntimeStatus
|
|
283
|
+
* @returns {void}
|
|
284
|
+
*/
|
|
285
|
+
const latchRuntimeError = () => {
|
|
286
|
+
if (runtimeStatusWritable()) Underpost.state.set(CONTAINER_STATUS_KEY, RUNTIME_STATUS.ERROR);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Marks the start pipeline's own completion. Written once, read only by the readinessProbe.
|
|
291
|
+
* @memberof RuntimeStatus
|
|
292
|
+
* @param {string} deployId
|
|
293
|
+
* @param {string} env
|
|
294
|
+
* @returns {void}
|
|
295
|
+
*/
|
|
296
|
+
const setStartContainerStatus = (deployId, env) => {
|
|
297
|
+
Underpost.state.set(START_CONTAINER_STATUS_KEY, containerStatusValue(deployId, env, RUNTIME_STATUS.RUNNING));
|
|
298
|
+
};
|
|
299
|
+
|
|
174
300
|
let internalServer;
|
|
175
301
|
|
|
176
302
|
/**
|
|
@@ -178,9 +304,10 @@ let internalServer;
|
|
|
178
304
|
* the already-listening server. Exposes only the three internal endpoints and
|
|
179
305
|
* never serves secrets or configuration.
|
|
180
306
|
*
|
|
181
|
-
* GET /_internal/status
|
|
182
|
-
* GET /_internal/ready
|
|
183
|
-
* GET /_internal/health
|
|
307
|
+
* GET /_internal/status → 200, `{status, deployId, env}` (monitor transport)
|
|
308
|
+
* GET /_internal/ready → 200 iff running-deployment, else 503 (readinessProbe)
|
|
309
|
+
* GET /_internal/health → 200 while the process is alive (livenessProbe)
|
|
310
|
+
* GET /_internal/telemetry → 200, state + health + metrics (telemetry agent)
|
|
184
311
|
*
|
|
185
312
|
* @memberof RuntimeStatus
|
|
186
313
|
* @param {number} [port]
|
|
@@ -208,6 +335,8 @@ const startInternalStatusServer = (port = resolveInternalStatusPort()) => {
|
|
|
208
335
|
: sendJson(503, { status: getRuntimeStatus() ?? null });
|
|
209
336
|
case INTERNAL_STATUS_PATH:
|
|
210
337
|
return sendJson(200, runtimeStatusPayload());
|
|
338
|
+
case INTERNAL_TELEMETRY_PATH:
|
|
339
|
+
return sendJson(200, runtimeTelemetryPayload());
|
|
211
340
|
default:
|
|
212
341
|
return sendJson(404, { error: 'not_found' });
|
|
213
342
|
}
|
|
@@ -236,16 +365,26 @@ export {
|
|
|
236
365
|
RUNTIME_STATUS,
|
|
237
366
|
CONTAINER_STATUS_KEY,
|
|
238
367
|
START_CONTAINER_STATUS_KEY,
|
|
368
|
+
AWAIT_DEPLOY_KEY,
|
|
239
369
|
INTERNAL_STATUS_PATH,
|
|
240
370
|
INTERNAL_READY_PATH,
|
|
241
371
|
INTERNAL_HEALTH_PATH,
|
|
372
|
+
INTERNAL_TELEMETRY_PATH,
|
|
242
373
|
resolveInternalStatusPort,
|
|
243
374
|
deployStatusPort,
|
|
244
375
|
containerStatusValue,
|
|
245
376
|
normalizeContainerStatus,
|
|
246
377
|
getRuntimeStatus,
|
|
247
378
|
getStartContainerStatus,
|
|
379
|
+
latchAwaitDeploy,
|
|
380
|
+
isAwaitingDeploy,
|
|
381
|
+
clearAwaitDeploy,
|
|
382
|
+
isTestRuntime,
|
|
383
|
+
latchRuntimeError,
|
|
384
|
+
runtimeStatusWritable,
|
|
385
|
+
setStartContainerStatus,
|
|
248
386
|
runtimeStatusPayload,
|
|
387
|
+
runtimeTelemetryPayload,
|
|
249
388
|
setRuntimeStatus,
|
|
250
389
|
startInternalStatusServer,
|
|
251
390
|
stopInternalStatusServer,
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
* The main runtime orchestrator responsible for reading configuration,
|
|
3
3
|
* initializing services (Prometheus, Ports, DB, Mailer), and building the
|
|
4
4
|
* specific server runtime for each host/path (e.g., nodejs, lampp).
|
|
5
|
-
* @module src/server/runtime.js
|
|
5
|
+
* @module src/server/runtime/runtime.js
|
|
6
6
|
* @namespace Runtime
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import * as promClient from 'prom-client';
|
|
10
10
|
|
|
11
|
-
import { loggerFactory } from '
|
|
12
|
-
import { newInstance } from '
|
|
13
|
-
import { Lampp } from '
|
|
14
|
-
import { WpService } from '
|
|
11
|
+
import { loggerFactory } from '../ops/logger.js';
|
|
12
|
+
import { newInstance } from '../../client/components/core/CommonJs.js';
|
|
13
|
+
import { Lampp } from '../../runtime/lampp/Lampp.js';
|
|
14
|
+
import { WpService } from '../../runtime/wp/Wp.js';
|
|
15
15
|
import { getInstanceContext, readConfJson } from './conf.js';
|
|
16
|
+
import { clearAwaitDeploy } from './runtime-status.js';
|
|
16
17
|
|
|
17
|
-
import ExpressService from '
|
|
18
|
+
import ExpressService from '../../runtime/express/Express.js';
|
|
18
19
|
|
|
19
|
-
import Underpost from '
|
|
20
|
+
import Underpost from '../../index.js';
|
|
20
21
|
|
|
21
22
|
const logger = loggerFactory(import.meta);
|
|
22
23
|
|
|
@@ -140,6 +141,7 @@ const buildRuntime = async () => {
|
|
|
140
141
|
path,
|
|
141
142
|
directory,
|
|
142
143
|
rootHostPath,
|
|
144
|
+
repository,
|
|
143
145
|
redirect,
|
|
144
146
|
redirectTarget,
|
|
145
147
|
resetRouter: currentPort === initPort,
|
|
@@ -176,7 +178,9 @@ const buildRuntime = async () => {
|
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
if (Lampp.enabled() && Lampp.router) Lampp.initService();
|
|
179
|
-
|
|
181
|
+
// Container-scoped boot latch, not host configuration: this releases the runtime this
|
|
182
|
+
// container just brought up, so it belongs to the same store as `container-status`.
|
|
183
|
+
clearAwaitDeploy();
|
|
180
184
|
Underpost.start.logRuntimeRouter();
|
|
181
185
|
};
|
|
182
186
|
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Manages the startup and runtime configuration of Underpost applications.
|
|
3
|
-
* @module src/server/start.js
|
|
3
|
+
* @module src/server/runtime/start.js
|
|
4
4
|
* @namespace UnderpostStartUp
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
8
|
import { awaitDeployMonitor } from './conf.js';
|
|
9
|
-
import { actionInitLog, loggerFactory } from '
|
|
10
|
-
import { shellCd, shellExec } from './process.js';
|
|
9
|
+
import { actionInitLog, loggerFactory } from '../ops/logger.js';
|
|
10
|
+
import { shellArgumentFactory, shellCd, shellExec, shellExecAsync } from './process.js';
|
|
11
11
|
import {
|
|
12
12
|
RUNTIME_STATUS,
|
|
13
|
-
START_CONTAINER_STATUS_KEY,
|
|
14
13
|
setRuntimeStatus,
|
|
15
14
|
startInternalStatusServer,
|
|
16
15
|
deployStatusPort,
|
|
17
|
-
|
|
16
|
+
setStartContainerStatus,
|
|
18
17
|
} from './runtime-status.js';
|
|
19
|
-
import Underpost from '
|
|
18
|
+
import Underpost from '../../index.js';
|
|
20
19
|
const logger = loggerFactory(import.meta);
|
|
21
20
|
|
|
21
|
+
// Every deployment builds and runs out of this path inside the workload container.
|
|
22
|
+
const ENGINE_PATH = '/home/dd/engine';
|
|
23
|
+
|
|
22
24
|
/**
|
|
23
25
|
* @class UnderpostStartUp
|
|
24
26
|
* @description Manages the startup and runtime configuration of Underpost applications.
|
|
@@ -139,9 +141,11 @@ class UnderpostStartUp {
|
|
|
139
141
|
* @param {boolean} options.build - Whether to build the deployment.
|
|
140
142
|
* @param {boolean} options.run - Whether to run the deployment.
|
|
141
143
|
* @param {boolean} options.underpostQuicklyInstall - Whether to use underpost quickly install.
|
|
142
|
-
* @param {boolean} options.
|
|
144
|
+
* @param {boolean} options.skipPullRepoBase - Whether to skip pulling the engine source repository.
|
|
145
|
+
* @param {boolean} options.skipPullPrivateRepo - Whether to skip cloning the private configuration repository.
|
|
143
146
|
* @param {boolean} options.skipFullBuild - Whether to skip building the full client bundle.
|
|
144
147
|
* @param {boolean} options.pullBundle - When true, download pre-built client bundle from Cloudinary via pull-bundle before starting.
|
|
148
|
+
* @param {boolean} options.privateTestRepo - When true, the base pull clones `engine-test-<id>` instead of `engine-<id>`.
|
|
145
149
|
*/
|
|
146
150
|
async callback(
|
|
147
151
|
deployId = 'dd-default',
|
|
@@ -150,11 +154,24 @@ class UnderpostStartUp {
|
|
|
150
154
|
build: false,
|
|
151
155
|
run: false,
|
|
152
156
|
underpostQuicklyInstall: false,
|
|
153
|
-
|
|
157
|
+
skipPullRepoBase: false,
|
|
158
|
+
skipPullPrivateRepo: false,
|
|
154
159
|
skipFullBuild: false,
|
|
155
160
|
pullBundle: false,
|
|
161
|
+
privateTestRepo: false,
|
|
156
162
|
},
|
|
157
163
|
) {
|
|
164
|
+
// Host configuration first: the pod command names only `start`, so the container env the
|
|
165
|
+
// `underpost-config` Secret injects is folded into the host configuration store here rather than by
|
|
166
|
+
// a second command the image's CLI might not have. A direct call, not a shell-out, so it
|
|
167
|
+
// does not depend on CLI surface either.
|
|
168
|
+
if (Underpost.state.isInsideContainer()) Underpost.host.load({ env });
|
|
169
|
+
|
|
170
|
+
// One phase, and the source pull belongs to `build`: a pod arrives here either through
|
|
171
|
+
// its bootstrap, which already replaced this checkout and linked the CLI, or with
|
|
172
|
+
// `--build` and no `--skip-pull-repo-base`, which pulls it here. Every long step shells
|
|
173
|
+
// out through `node bin`, so those run the pulled source either way.
|
|
174
|
+
//
|
|
158
175
|
// Bring the internal status endpoint up first so Phase-2 readiness is
|
|
159
176
|
// observable through every lifecycle phase, including build and init. Bind
|
|
160
177
|
// the deployment-resolved port so it always matches the monitor's target.
|
|
@@ -167,15 +184,85 @@ class UnderpostStartUp {
|
|
|
167
184
|
} catch (error) {
|
|
168
185
|
logger.error('Deployment build/init failed', { deployId, env, message: error?.message });
|
|
169
186
|
setRuntimeStatus(deployId, env, RUNTIME_STATUS.ERROR);
|
|
170
|
-
if (!Underpost.
|
|
187
|
+
if (!Underpost.state.isInsideContainer()) throw error;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
/**
|
|
191
|
+
* Replaces `/home/dd/engine` with the deployment's own source and points the global
|
|
192
|
+
* `underpost` command at it — the base pull that makes the rest of the flow independent
|
|
193
|
+
* of how recently the npm package was published.
|
|
194
|
+
*
|
|
195
|
+
* One pull per container: {@link UnderpostStartUp.build} performs it unless
|
|
196
|
+
* `--skip-pull-repo-base` says the pod's own bootstrap (`pod_bootstrap_cmd`) already
|
|
197
|
+
* replaced the checkout and linked the CLI before `start` was ever invoked.
|
|
198
|
+
* @param {string} deployId - The ID of the deployment.
|
|
199
|
+
* @param {Object} [options] - Options for the pull.
|
|
200
|
+
* @param {boolean} [options.underpostQuicklyInstall] - Use `underpost install` instead of `npm install`.
|
|
201
|
+
* @param {boolean} [options.privateTestRepo] - Clone `engine-test-<id>` instead of `engine-<id>`.
|
|
202
|
+
* @memberof UnderpostStartUp
|
|
203
|
+
*/
|
|
204
|
+
pullRepoBase(deployId = 'dd-default', options = {}) {
|
|
205
|
+
const buildBasePath = `/home/dd`;
|
|
206
|
+
// `--private-test-repo` clones the isolated test source repo published by
|
|
207
|
+
// `node bin/build <deployId> --update-private`, instead of the production one.
|
|
208
|
+
const repoName = Underpost.repo.engineRepoFactory(deployId, { test: options?.privateTestRepo === true });
|
|
209
|
+
shellExec(`cd ${buildBasePath} && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}`);
|
|
210
|
+
shellExec(`mkdir -p ${ENGINE_PATH}`);
|
|
211
|
+
shellExec(`cd ${buildBasePath} && sudo cp -a ./${repoName}/. ./engine`);
|
|
212
|
+
shellExec(`cd ${buildBasePath} && sudo rm -rf ./${repoName}`);
|
|
213
|
+
shellCd(ENGINE_PATH);
|
|
214
|
+
// Dependencies before the link: stage 2 boots through this checkout's `bin/index.js`
|
|
215
|
+
// and cannot start without its node_modules.
|
|
216
|
+
shellExec(options?.underpostQuicklyInstall ? `underpost install` : `npm install`);
|
|
217
|
+
Underpost.start.linkRuntimeCli();
|
|
218
|
+
},
|
|
219
|
+
/**
|
|
220
|
+
* Repoints the global `underpost` command at the engine checkout.
|
|
221
|
+
*
|
|
222
|
+
* `--force` because the image already owns a global `underpost` from npm; without it npm
|
|
223
|
+
* refuses the bin with `EEXIST`. Only the bin is repointed — the published package
|
|
224
|
+
* directory stays in place, so `getUnderpostRootPath()` keeps resolving to it and both
|
|
225
|
+
* stages share the one container state store holding `container-status`.
|
|
226
|
+
*
|
|
227
|
+
* Failure is not fatal. A host that cannot write its global prefix falls back to the npm
|
|
228
|
+
* snapshot, which is exactly the behaviour before this step existed, rather than losing
|
|
229
|
+
* the deployment over a link.
|
|
230
|
+
* @param {string} [enginePath] - Checkout to link.
|
|
231
|
+
* @returns {boolean} Whether the global command now resolves to the checkout.
|
|
232
|
+
* @memberof UnderpostStartUp
|
|
233
|
+
*/
|
|
234
|
+
linkRuntimeCli(enginePath = ENGINE_PATH) {
|
|
235
|
+
const checkout = shellArgumentFactory(enginePath);
|
|
236
|
+
const result = shellExec(
|
|
237
|
+
`cd ${checkout} && npm link --force && ` +
|
|
238
|
+
`test "$(readlink -f "$(command -v underpost)")" = "$(readlink -f ./bin/index.js)"`,
|
|
239
|
+
{
|
|
240
|
+
silent: true,
|
|
241
|
+
silentOnError: true,
|
|
242
|
+
},
|
|
243
|
+
);
|
|
244
|
+
if (result?.code === 0) {
|
|
245
|
+
logger.info('Global underpost CLI linked to the engine checkout', { enginePath });
|
|
246
|
+
return true;
|
|
171
247
|
}
|
|
248
|
+
logger.warn('Could not link the global underpost CLI; continuing with the image snapshot', {
|
|
249
|
+
enginePath,
|
|
250
|
+
code: result?.code,
|
|
251
|
+
stderr: `${result?.stderr ?? ''}`.trim().split('\n').slice(-1)[0],
|
|
252
|
+
});
|
|
253
|
+
return false;
|
|
172
254
|
},
|
|
173
255
|
/**
|
|
174
|
-
*
|
|
256
|
+
* Materializes the deployment environment and builds the client bundle.
|
|
257
|
+
*
|
|
258
|
+
* Container-specific values are not applied by a script here: `app load` resolves the
|
|
259
|
+
* deployment's `.env.<env>.oci` overlay when it runs inside a container, so the working tree
|
|
260
|
+
* this build renders from already carries the cluster endpoints.
|
|
175
261
|
* @param {string} deployId - The ID of the deployment.
|
|
176
262
|
* @param {string} env - The environment of the deployment.
|
|
177
263
|
* @param {Object} options - Options for the build.
|
|
178
|
-
* @param {boolean} options.
|
|
264
|
+
* @param {boolean} options.skipPullRepoBase - Whether to skip pulling the engine source repository and use the current workspace code directly.
|
|
265
|
+
* @param {boolean} options.skipPullPrivateRepo - Whether to skip cloning the private configuration repository, for a pod whose bootstrap already placed `engine-private`.
|
|
179
266
|
* @param {boolean} options.underpostQuicklyInstall - Whether to use underpost quickly install.
|
|
180
267
|
* @param {boolean} options.skipFullBuild - Whether to skip building the full client bundle.
|
|
181
268
|
* @param {boolean} options.pullBundle - When true, download pre-built client bundle from Cloudinary via pull-bundle (must be pushed first with push-bundle).
|
|
@@ -187,31 +274,29 @@ class UnderpostStartUp {
|
|
|
187
274
|
async build(
|
|
188
275
|
deployId = 'dd-default',
|
|
189
276
|
env = 'development',
|
|
190
|
-
options = {
|
|
277
|
+
options = {
|
|
278
|
+
underpostQuicklyInstall: false,
|
|
279
|
+
skipPullRepoBase: false,
|
|
280
|
+
skipPullPrivateRepo: false,
|
|
281
|
+
skipFullBuild: false,
|
|
282
|
+
pullBundle: false,
|
|
283
|
+
},
|
|
191
284
|
) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
shellExec(`node bin env ${deployId} ${env}`);
|
|
208
|
-
if (fs.existsSync('./engine-private/itc-scripts')) {
|
|
209
|
-
const itcScripts = await fs.readdir('./engine-private/itc-scripts');
|
|
210
|
-
for (const itcScript of itcScripts)
|
|
211
|
-
if (itcScript.match(deployId)) shellExec(`node ./engine-private/itc-scripts/${itcScript}`);
|
|
212
|
-
}
|
|
213
|
-
if (options.pullBundle === true) shellExec(`node bin run pull-bundle --deploy-id ${deployId}`);
|
|
214
|
-
else if (!options.skipFullBuild) shellExec(`node bin client ${deployId}`);
|
|
285
|
+
if (options.skipPullRepoBase !== true) Underpost.start.pullRepoBase(deployId, options);
|
|
286
|
+
shellCd(ENGINE_PATH);
|
|
287
|
+
// Containers refresh private config because an image/bootstrap checkout may be stale.
|
|
288
|
+
// Hosts keep their local checkout, while explicit skip preserves caller-provided config.
|
|
289
|
+
if (options.skipPullPrivateRepo !== true)
|
|
290
|
+
Underpost.repo.privateEngineRepoFactory(deployId, { force: Underpost.state.isInsideContainer() });
|
|
291
|
+
// Awaited rather than blocking: these are the minutes-long steps of a deployment, and a
|
|
292
|
+
// synchronous child stalls the event loop for its whole duration — leaving the status
|
|
293
|
+
// endpoint bound but unable to answer, so telemetry went dark across the entire build.
|
|
294
|
+
await shellExecAsync(options?.underpostQuicklyInstall ? `underpost install` : `npm install`);
|
|
295
|
+
await shellExecAsync(`node bin app load --env ${env} --args deploy-id=${deployId}`);
|
|
296
|
+
if (options.pullBundle === true) await shellExecAsync(`node bin run pull-bundle --deploy-id ${deployId}`);
|
|
297
|
+
// `--env` is explicit rather than inherited: the container's ambient NODE_ENV comes from
|
|
298
|
+
// the injected `underpost-config`, and a build that guesses it renders the wrong conf.
|
|
299
|
+
else if (!options.skipFullBuild) await shellExecAsync(`node bin client ${deployId} --env ${env}`);
|
|
215
300
|
},
|
|
216
301
|
/**
|
|
217
302
|
* Runs a deployment.
|
|
@@ -232,7 +317,7 @@ class UnderpostStartUp {
|
|
|
232
317
|
const replicas = await fs.readdir(`./engine-private/replica`);
|
|
233
318
|
for (const replica of replicas) {
|
|
234
319
|
if (!replica.match(deployId)) continue;
|
|
235
|
-
shellExec(`node bin env ${
|
|
320
|
+
shellExec(`node bin app load --env ${env} --args deploy-id=${replica}`);
|
|
236
321
|
const replicaCmd = `npm ${runCmd} ${replica}`;
|
|
237
322
|
shellExec(replicaCmd, { async: true, callback: makeDeployCallback(replicaCmd) });
|
|
238
323
|
const result = await awaitDeployMonitor();
|
|
@@ -242,15 +327,19 @@ class UnderpostStartUp {
|
|
|
242
327
|
}
|
|
243
328
|
}
|
|
244
329
|
}
|
|
245
|
-
shellExec(`node bin env ${
|
|
330
|
+
shellExec(`node bin app load --env ${env} --args deploy-id=${deployId}`);
|
|
246
331
|
const deployCmd = `npm ${runCmd} ${deployId}`;
|
|
247
332
|
shellExec(deployCmd, { async: true, callback: makeDeployCallback(deployCmd) });
|
|
248
333
|
const result = await awaitDeployMonitor(true);
|
|
249
334
|
if (result === true) {
|
|
250
|
-
|
|
335
|
+
// Withdraw every domain's local traces once the deployment is serving. Three calls
|
|
336
|
+
// rather than one cross-domain sweep: each domain owns what it put on disk.
|
|
337
|
+
if (env === 'production' && Underpost.state.isInsideContainer())
|
|
338
|
+
for (const domain of [Underpost.secret, Underpost.host, Underpost.app])
|
|
339
|
+
domain.clean({ env, namespace: 'default', args: {}, dryRun: false, force: false });
|
|
251
340
|
setTimeout(() => {
|
|
252
341
|
setRuntimeStatus(deployId, env, RUNTIME_STATUS.RUNNING);
|
|
253
|
-
|
|
342
|
+
setStartContainerStatus(deployId, env);
|
|
254
343
|
});
|
|
255
344
|
} else {
|
|
256
345
|
setRuntimeStatus(deployId, env, RUNTIME_STATUS.ERROR);
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module for managing identity and authorization
|
|
3
|
-
* @module src/server/auth.js
|
|
3
|
+
* @module src/server/security/auth.js
|
|
4
4
|
* @namespace Auth
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import jwt from 'jsonwebtoken';
|
|
8
|
-
import { loggerFactory } from '
|
|
8
|
+
import { loggerFactory } from '../ops/logger.js';
|
|
9
9
|
import crypto from 'crypto';
|
|
10
10
|
import { promisify } from 'util';
|
|
11
|
-
import { UserDto } from '
|
|
11
|
+
import { UserDto } from '../../api/user/user.model.js';
|
|
12
12
|
import {
|
|
13
13
|
commonAdminGuard,
|
|
14
14
|
commonModeratorGuard,
|
|
15
15
|
commonUserGuard,
|
|
16
16
|
validatePassword,
|
|
17
|
-
} from '
|
|
17
|
+
} from '../../client/components/core/CommonJs.js';
|
|
18
18
|
import helmet from 'helmet';
|
|
19
19
|
import rateLimit from 'express-rate-limit';
|
|
20
20
|
import slowDown from 'express-slow-down';
|
|
21
21
|
import cors from 'cors';
|
|
22
22
|
import cookieParser from 'cookie-parser';
|
|
23
|
-
import { DataBaseProviderService } from '
|
|
24
|
-
import { isDevProxyContext } from '
|
|
23
|
+
import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
|
|
24
|
+
import { isDevProxyContext } from '../runtime/conf.js';
|
|
25
25
|
|
|
26
26
|
const logger = loggerFactory(import.meta);
|
|
27
27
|
|
|
@@ -618,7 +618,7 @@ function applySecurity(app, opts = {}) {
|
|
|
618
618
|
|
|
619
619
|
// Other helpful Helmet policies
|
|
620
620
|
app.use(helmet.noSniff()); // X-Content-Type-Options: nosniff
|
|
621
|
-
app.use(helmet.frameguard({ action: '
|
|
621
|
+
app.use(helmet.frameguard({ action: 'sameorigin' }));
|
|
622
622
|
app.use(helmet.referrerPolicy({ policy: 'no-referrer-when-downgrade' }));
|
|
623
623
|
|
|
624
624
|
// Content-Security-Policy: include nonce from res.locals
|
|
@@ -630,7 +630,6 @@ function applySecurity(app, opts = {}) {
|
|
|
630
630
|
directives: {
|
|
631
631
|
defaultSrc: ["'self'"],
|
|
632
632
|
baseUri: ["'self'"],
|
|
633
|
-
blockAllMixedContent: [],
|
|
634
633
|
fontSrc: ["'self'", httpDirective, 'data:'],
|
|
635
634
|
frameAncestors: frameAncestors,
|
|
636
635
|
imgSrc: ["'self'", 'data:', httpDirective, 'https:', 'blob:'],
|