@underpostnet/cyberia 3.3.0 → 3.3.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +1 -0
- package/.github/workflows/coverall.cyberia.ci.yml +34 -14
- package/.github/workflows/cyberia-client.cd.yml +5 -0
- package/.github/workflows/cyberia-server.cd.yml +5 -0
- 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 +3 -0
- package/.github/workflows/engine-cyberia.ci.yml +4 -5
- package/.github/workflows/ghpkg.ci.yml +35 -20
- package/.github/workflows/hardhat.ci.yml +12 -11
- package/.github/workflows/npmpkg.ci.yml +17 -15
- package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
- package/.github/workflows/release.cd.yml +1 -0
- package/.prettierignore +1 -0
- package/AGENTS.md +47 -0
- package/CHANGELOG.md +565 -2510
- package/CLI-HELP.md +306 -147
- package/Dockerfile +25 -9
- package/Dockerfile.dev +25 -9
- package/Dockerfile.test +4 -4
- package/README.md +21 -1
- package/bin/build.js +66 -41
- package/bin/build.template.js +8 -3
- package/bin/cyberia.js +308 -91
- package/bin/deploy.js +18 -104
- package/bin/index.js +308 -91
- package/conf.js +91 -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 +6 -26
- package/deploy/dd-cyberia/init.sh +35 -43
- package/deploy/dd-cyberia/package.sh +17 -0
- package/deploy/dd-cyberia/state.sh +14 -0
- package/deploy/dd-cyberia/sync-deploy.sh +92 -170
- 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 +12 -39
- package/deploy/release/deploy.sh +9 -39
- package/deployment.yaml +7 -2
- package/docker-compose.yml +7 -7
- 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 +101 -40
- package/hardhat/package.json +2 -2
- package/manifests/alertmanager/deployment.yaml +81 -0
- package/manifests/blackbox-exporter/deployment.yaml +75 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
- 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/event-monitor.sh +56 -0
- package/scripts/k3s-node-setup.sh +27 -14
- package/scripts/kubeadm-node-setup.sh +31 -11
- package/scripts/maas-setup.sh +8 -8
- 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-world.js +8 -0
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
- package/src/api/cyberia-instance/cyberia-instance.controller.js +1 -1
- package/src/api/cyberia-instance/cyberia-instance.router.js +2 -2
- package/src/api/cyberia-instance/cyberia-instance.service.js +2 -2
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
- 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 +0 -26
- 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.router.js +2 -2
- package/src/api/object-layer/object-layer.service.js +3 -3
- 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 -35
- package/src/cli/client.js +306 -0
- package/src/cli/cloud-init.js +3 -3
- package/src/cli/cluster.js +184 -82
- package/src/cli/db.js +120 -68
- package/src/cli/deploy.js +153 -71
- 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 -6
- package/src/cli/index.js +322 -142
- 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 +16 -12
- package/src/cli/repository.js +558 -363
- package/src/cli/run.js +331 -650
- package/src/cli/secrets.js +2158 -964
- package/src/cli/ssh.js +478 -279
- package/src/cli/state.js +394 -0
- package/src/cli/static.js +2 -2
- package/src/cli/system.js +1 -1
- package/src/cli/test.js +199 -125
- package/src/cli/vultr.js +61 -21
- package/src/cli/wireguard.js +1111 -306
- 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-portal/AppShellCyberiaPortal.js +2 -1
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
- 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/CYBERIA-CLI.md +32 -5
- 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/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 +38 -30
- 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 +7 -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 +79 -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 +53 -10
- package/src/projects/cyberia/gemini-client.js +1 -1
- package/src/projects/cyberia/generate-saga.js +1 -1
- package/src/projects/cyberia/hot-reload-trigger.js +1 -1
- package/src/projects/cyberia/instance-data.js +1 -1
- 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 +1 -1
- package/src/projects/cyberia/semantic-layer-generator.js +1 -1
- package/src/projects/underpost/catalog-underpost.js +9 -1
- 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/docker-compose.yml +7 -7
- 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} +144 -11
- package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
- package/src/server/{middlewares.js → network/middlewares.js} +3 -3
- 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/{underpost-compression.js → network/underpost-compression.js} +1 -1
- package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
- package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
- package/src/server/{cri.js → ops/cri.js} +2 -2
- package/src/server/{cron.js → ops/cron.js} +349 -74
- 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/{systemd.js → ops/systemd.js} +55 -1
- package/src/server/{conf.js → runtime/conf.js} +513 -422
- 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 -12
- 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/{selinux.js → security/selinux.js} +1 -1
- 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} +1 -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/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
- 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/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +609 -55
- 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} +6 -6
- package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -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/deploy/lib/logging.sh +0 -96
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
- package/manifests/mongodb/pv-pvc.yaml +0 -59
- package/scripts/coverall-test-cyberia.sh +0 -24
- package/scripts/coverall-test.sh +0 -24
- 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/environment.js +0 -98
package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js}
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @description End-to-end test of the two-phase deployment readiness contract
|
|
4
4
|
* between the in-pod runtime (`start.js` / `runtime-status.js`) and the CD-runner
|
|
5
5
|
* monitor (`Underpost.monitor.monitorReadyRunner`), exercised as real OS
|
|
6
|
-
* processes coordinating through the shared
|
|
6
|
+
* processes coordinating through the shared host configuration store and a real HTTP
|
|
7
7
|
* internal status endpoint.
|
|
8
8
|
*
|
|
9
9
|
* Contract under test:
|
|
@@ -36,12 +36,12 @@ import fs from 'fs-extra';
|
|
|
36
36
|
import os from 'node:os';
|
|
37
37
|
import path from 'node:path';
|
|
38
38
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
39
|
-
import Underpost from '
|
|
40
|
-
import { shellExec } from '
|
|
41
|
-
import { startInternalStatusServer, stopInternalStatusServer } from '
|
|
39
|
+
import Underpost from '../../../../src/index.js';
|
|
40
|
+
import { shellExec } from '../../../../src/server/runtime/process.js';
|
|
41
|
+
import { startInternalStatusServer, stopInternalStatusServer } from '../../../../src/server/runtime/runtime-status.js';
|
|
42
42
|
|
|
43
43
|
const node = process.execPath;
|
|
44
|
-
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '
|
|
44
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
|
|
45
45
|
|
|
46
46
|
const DEPLOY_ID = 'dd-test';
|
|
47
47
|
const ENV = 'production';
|
|
@@ -54,24 +54,22 @@ const BUILD_STATUS = `${DEPLOY_ID}-${ENV}-build-deployment`;
|
|
|
54
54
|
const INTERNAL_PORT = 39517; // internal status endpoint (real server bound here)
|
|
55
55
|
const CLOSED_PORT = 39518; // no server — used to force a transport failure
|
|
56
56
|
|
|
57
|
-
describe('Deploy monitor — two-phase state machine (e2e, real HTTP transport)',
|
|
58
|
-
this.timeout(60000);
|
|
59
|
-
|
|
57
|
+
describe('Deploy monitor — two-phase state machine (e2e, real HTTP transport)', { timeout: 60000 }, () => {
|
|
60
58
|
let prevPrefix;
|
|
61
59
|
let tmpPrefix;
|
|
62
60
|
let fakeBinDir;
|
|
63
|
-
let
|
|
61
|
+
let stateFile;
|
|
64
62
|
let monitorScriptPath;
|
|
65
63
|
|
|
66
|
-
|
|
64
|
+
beforeAll(() => {
|
|
67
65
|
prevPrefix = process.env.npm_config_prefix;
|
|
68
66
|
tmpPrefix = fs.mkdtempSync(path.join(os.tmpdir(), 'underpost-e2e-'));
|
|
69
67
|
process.env.npm_config_prefix = tmpPrefix;
|
|
70
68
|
|
|
71
|
-
Underpost.
|
|
72
|
-
Underpost.
|
|
69
|
+
Underpost.state.set('container-status', 'init');
|
|
70
|
+
Underpost.state.set('start-container-status', '');
|
|
73
71
|
const npmRoot = shellExec('npm root -g', { stdout: true, silent: true, disableLog: true }).trim();
|
|
74
|
-
|
|
72
|
+
stateFile = path.join(npmRoot, 'underpost', '.state');
|
|
75
73
|
|
|
76
74
|
process.env.UNDERPOST_INTERNAL_PORT = String(INTERNAL_PORT);
|
|
77
75
|
startInternalStatusServer(INTERNAL_PORT);
|
|
@@ -107,7 +105,7 @@ if [[ "$verb" == "port-forward" ]]; then
|
|
|
107
105
|
exit 0
|
|
108
106
|
fi
|
|
109
107
|
if [[ "$verb" == "exec" ]]; then
|
|
110
|
-
grep -E '^container-status=' "$
|
|
108
|
+
grep -E '^container-status=' "$UNDERPOST_STATE_FILE" 2>/dev/null | tail -n1 | sed -E 's/^container-status=//'
|
|
111
109
|
exit 0
|
|
112
110
|
fi
|
|
113
111
|
exit 0
|
|
@@ -135,7 +133,7 @@ try {
|
|
|
135
133
|
);
|
|
136
134
|
});
|
|
137
135
|
|
|
138
|
-
|
|
136
|
+
afterAll(async () => {
|
|
139
137
|
await stopInternalStatusServer();
|
|
140
138
|
delete process.env.UNDERPOST_INTERNAL_PORT;
|
|
141
139
|
if (prevPrefix === undefined) delete process.env.npm_config_prefix;
|
|
@@ -145,17 +143,17 @@ try {
|
|
|
145
143
|
|
|
146
144
|
beforeEach(() => {
|
|
147
145
|
// Deploy in flight: app not yet reporting running.
|
|
148
|
-
Underpost.
|
|
146
|
+
Underpost.state.set('container-status', INIT_STATUS);
|
|
149
147
|
// start-container-status is unset (empty) — the readinessProbe
|
|
150
148
|
// sees 503 until the start pipeline completes and stamps this key.
|
|
151
|
-
Underpost.
|
|
149
|
+
Underpost.state.set('start-container-status', '');
|
|
152
150
|
});
|
|
153
151
|
|
|
154
152
|
const spawnMonitor = (overrides = {}) =>
|
|
155
153
|
new Promise((resolve) => {
|
|
156
154
|
const envVars = {
|
|
157
155
|
PATH: `${fakeBinDir}:${process.env.PATH}`,
|
|
158
|
-
|
|
156
|
+
UNDERPOST_STATE_FILE: stateFile,
|
|
159
157
|
POD_NAME,
|
|
160
158
|
npm_config_prefix: tmpPrefix,
|
|
161
159
|
UNDERPOST_INTERNAL_PORT: String(INTERNAL_PORT),
|
|
@@ -178,7 +176,7 @@ try {
|
|
|
178
176
|
});
|
|
179
177
|
|
|
180
178
|
it('success (default exec transport): both phases satisfied → monitor exits 0', async () => {
|
|
181
|
-
Underpost.
|
|
179
|
+
Underpost.state.set('container-status', RUNNING_STATUS);
|
|
182
180
|
// start-container-status not needed for monitor (reads container-status);
|
|
183
181
|
// this test exercises the default exec transport path.
|
|
184
182
|
const code = await spawnMonitor({ FAKE_POD_READY: 'True' });
|
|
@@ -186,21 +184,21 @@ try {
|
|
|
186
184
|
});
|
|
187
185
|
|
|
188
186
|
it('success (opt-in http transport): both phases satisfied → monitor exits 0', async () => {
|
|
189
|
-
Underpost.
|
|
190
|
-
Underpost.
|
|
187
|
+
Underpost.state.set('container-status', RUNNING_STATUS);
|
|
188
|
+
Underpost.state.set('start-container-status', RUNNING_STATUS);
|
|
191
189
|
const code = await spawnMonitor({ FAKE_POD_READY: 'True', MON_TRANSPORT: 'http' });
|
|
192
190
|
expect(code).to.equal(0);
|
|
193
191
|
});
|
|
194
192
|
|
|
195
193
|
it('runtime failure: container-status=error → monitor exits 1', async () => {
|
|
196
194
|
const monitorExit = spawnMonitor({ FAKE_POD_READY: 'True' });
|
|
197
|
-
Underpost.
|
|
195
|
+
Underpost.state.set('container-status', 'error');
|
|
198
196
|
expect(await monitorExit).to.equal(1);
|
|
199
197
|
});
|
|
200
198
|
|
|
201
199
|
it('readiness mismatch: runtime running but pod not Ready → never succeeds (exits 1)', async () => {
|
|
202
200
|
// Phase 2 satisfied, Phase 1 not: success requires BOTH, so it must time out.
|
|
203
|
-
Underpost.
|
|
201
|
+
Underpost.state.set('container-status', RUNNING_STATUS);
|
|
204
202
|
// start-container-status is NOT set — the readinessProbe would fail,
|
|
205
203
|
// but the monitor only checks container-status via exec/http transport.
|
|
206
204
|
const code = await spawnMonitor({ FAKE_POD_READY: 'False', UNDERPOST_MONITOR_MAX_ITERATIONS: '4' });
|
|
@@ -208,7 +206,7 @@ try {
|
|
|
208
206
|
});
|
|
209
207
|
|
|
210
208
|
it('transport failure (http): endpoint unreachable is never success (exits 1)', async () => {
|
|
211
|
-
Underpost.
|
|
209
|
+
Underpost.state.set('container-status', RUNNING_STATUS);
|
|
212
210
|
const code = await spawnMonitor({
|
|
213
211
|
MON_TRANSPORT: 'http',
|
|
214
212
|
UNDERPOST_INTERNAL_PORT: String(CLOSED_PORT),
|
|
@@ -219,7 +217,7 @@ try {
|
|
|
219
217
|
});
|
|
220
218
|
|
|
221
219
|
it('timeout: runtime stuck initializing → monitor exits 1', async () => {
|
|
222
|
-
Underpost.
|
|
220
|
+
Underpost.state.set('container-status', INIT_STATUS);
|
|
223
221
|
// start-container-status remains unset — readinessProbe returns 503
|
|
224
222
|
// (correct, since the runtime is still initializing).
|
|
225
223
|
const code = await spawnMonitor({ FAKE_POD_READY: 'True', UNDERPOST_MONITOR_MAX_ITERATIONS: '4' });
|
|
@@ -229,15 +227,15 @@ try {
|
|
|
229
227
|
it('regression: advanced pod whose runtime status falls back → monitor exits 1', async () => {
|
|
230
228
|
// Pod advances past build, then its reported status regresses (pod restart);
|
|
231
229
|
// the monitor must treat this as a failure rather than wait it out.
|
|
232
|
-
Underpost.
|
|
230
|
+
Underpost.state.set('container-status', INIT_STATUS);
|
|
233
231
|
const monitorExit = spawnMonitor({ FAKE_POD_READY: 'False', UNDERPOST_MONITOR_MAX_ITERATIONS: '120' });
|
|
234
232
|
await new Promise((r) => setTimeout(r, 1500));
|
|
235
|
-
Underpost.
|
|
233
|
+
Underpost.state.set('container-status', BUILD_STATUS);
|
|
236
234
|
expect(await monitorExit).to.equal(1);
|
|
237
235
|
});
|
|
238
236
|
|
|
239
237
|
it('readinessProbe: start-container-status set → returns 200 (probe passes)', async () => {
|
|
240
|
-
Underpost.
|
|
238
|
+
Underpost.state.set('start-container-status', RUNNING_STATUS);
|
|
241
239
|
const res = await fetch(`http://127.0.0.1:${INTERNAL_PORT}/_internal/ready`);
|
|
242
240
|
expect(res.status).to.equal(200);
|
|
243
241
|
const body = await res.json();
|
|
@@ -246,7 +244,7 @@ try {
|
|
|
246
244
|
|
|
247
245
|
it('readinessProbe: start-container-status unset → returns 503 (probe fails)', async () => {
|
|
248
246
|
// Unset from beforeEach re-stamp; clear it.
|
|
249
|
-
Underpost.
|
|
247
|
+
Underpost.state.set('start-container-status', '');
|
|
250
248
|
const res = await fetch(`http://127.0.0.1:${INTERNAL_PORT}/_internal/ready`);
|
|
251
249
|
expect(res.status).to.equal(503);
|
|
252
250
|
});
|
|
@@ -254,14 +252,14 @@ try {
|
|
|
254
252
|
// Custom instances (cyberia-*) gate on K8s Ready and read status via exec;
|
|
255
253
|
// their runtime never stamps `running-deployment` (stays `initializing`).
|
|
256
254
|
it('instance (kubernetes gate + exec): K8s Ready with initializing status → exits 0', async () => {
|
|
257
|
-
Underpost.
|
|
255
|
+
Underpost.state.set('container-status', INIT_STATUS);
|
|
258
256
|
const code = await spawnMonitor({ FAKE_POD_READY: 'True', MON_READY_GATE: 'kubernetes', MON_TRANSPORT: 'exec' });
|
|
259
257
|
expect(code).to.equal(0);
|
|
260
258
|
});
|
|
261
259
|
|
|
262
260
|
it('instance (kubernetes gate + exec): container-status=error → exits 1', async () => {
|
|
263
261
|
const monitorExit = spawnMonitor({ FAKE_POD_READY: 'True', MON_READY_GATE: 'kubernetes', MON_TRANSPORT: 'exec' });
|
|
264
|
-
Underpost.
|
|
262
|
+
Underpost.state.set('container-status', 'error');
|
|
265
263
|
expect(await monitorExit).to.equal(1);
|
|
266
264
|
});
|
|
267
265
|
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { MailerProviderClass } from '../../../../src/mailer/MailerProvider.js';
|
|
5
|
+
import { mailerInterceptorFactory } from '../../../../src/mailer/MailerInterceptor.js';
|
|
6
|
+
import {
|
|
7
|
+
EVENT_CONF_PATH,
|
|
8
|
+
assertNotificationRoutes,
|
|
9
|
+
eventNotificationRoutes,
|
|
10
|
+
} from '../../../../src/server/ops/event-notification.js';
|
|
11
|
+
|
|
12
|
+
const CONF = {
|
|
13
|
+
'notification-providers': {
|
|
14
|
+
'default-cluster-mailer-provider': {
|
|
15
|
+
type: 'mailer',
|
|
16
|
+
mailer: {
|
|
17
|
+
sender: { email: 'env:CLUSTER_MAILER_ADMIN_SENDER_EMAIL', name: 'env:CLUSTER_MAILER_ADMIN_SENDER_NAME' },
|
|
18
|
+
transport: {
|
|
19
|
+
host: 'env:CLUSTER_MAILER_SMTP_HOST',
|
|
20
|
+
port: 'env:CLUSTER_MAILER_SMTP_PORT',
|
|
21
|
+
secure: 'env:CLUSTER_SMTP_SECURE',
|
|
22
|
+
auth: { user: 'env:CLUSTER_MAILER_SMTP_AUTH_USER', pass: 'env:CLUSTER_MAILER_SMTP_AUTH_PASS' },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
events: {
|
|
28
|
+
'wireguard-server-down': {
|
|
29
|
+
notifications: [
|
|
30
|
+
{
|
|
31
|
+
'notification-provider-id': 'default-cluster-mailer-provider',
|
|
32
|
+
payload: { subscribers: [{ email: 'ops@example.com', name: 'Ops' }] },
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const loadedProviderFactory = async () => {
|
|
40
|
+
const provider = new MailerProviderClass();
|
|
41
|
+
await provider.load({
|
|
42
|
+
id: 'test',
|
|
43
|
+
sender: { email: 'sender@example.com', name: 'Sender' },
|
|
44
|
+
transport: { host: 'smtp.example.com', port: 587, secure: false, auth: { user: '', pass: '' } },
|
|
45
|
+
templates: {},
|
|
46
|
+
});
|
|
47
|
+
return provider;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
describe('event notification contract', () => {
|
|
51
|
+
it('resolves a declared route without reading any credential', () => {
|
|
52
|
+
const [route] = eventNotificationRoutes('wireguard-server-down', CONF);
|
|
53
|
+
expect(route.error).to.equal(undefined);
|
|
54
|
+
expect(route.providerId).to.equal('default-cluster-mailer-provider');
|
|
55
|
+
expect(route.type).to.equal('mailer');
|
|
56
|
+
expect(route.target).to.equal('smtp (env)');
|
|
57
|
+
expect(route.recipients).to.deep.equal([
|
|
58
|
+
{ email: 'ops@example.com', name: 'Ops', address: 'Ops <ops@example.com>' },
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('reports an event that declares no notification', () => {
|
|
63
|
+
const [route] = eventNotificationRoutes('wireguard-spoke-down', CONF);
|
|
64
|
+
expect(route.error).to.include(EVENT_CONF_PATH);
|
|
65
|
+
expect(route.error).to.include('wireguard-spoke-down');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('reports a route naming an undeclared provider', () => {
|
|
69
|
+
const conf = {
|
|
70
|
+
...CONF,
|
|
71
|
+
events: { 'x-down': { notifications: [{ 'notification-provider-id': 'ghost', payload: {} }] } },
|
|
72
|
+
};
|
|
73
|
+
expect(eventNotificationRoutes('x-down', conf)[0].error).to.include("'ghost' is not declared");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('reports a provider type nothing can deliver', () => {
|
|
77
|
+
const conf = {
|
|
78
|
+
'notification-providers': { pager: { type: 'pager' } },
|
|
79
|
+
events: {
|
|
80
|
+
'x-down': {
|
|
81
|
+
notifications: [{ 'notification-provider-id': 'pager', payload: { subscribers: [{ email: 'a@b.com' }] } }],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
expect(eventNotificationRoutes('x-down', conf)[0].error).to.include(
|
|
86
|
+
"unsupported notification provider type 'pager'",
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('reports a route with no subscriber to deliver to', () => {
|
|
91
|
+
const conf = {
|
|
92
|
+
...CONF,
|
|
93
|
+
events: {
|
|
94
|
+
'x-down': {
|
|
95
|
+
notifications: [
|
|
96
|
+
{
|
|
97
|
+
'notification-provider-id': 'default-cluster-mailer-provider',
|
|
98
|
+
payload: { subscribers: [{ name: 'Ops' }] },
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
expect(eventNotificationRoutes('x-down', conf)[0].error).to.include('no subscriber with an email');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('refuses detection whose outcome would reach nobody', () => {
|
|
108
|
+
expect(() => assertNotificationRoutes(eventNotificationRoutes('wireguard-spoke-down', CONF))).to.throw(
|
|
109
|
+
'notification routes are unresolved',
|
|
110
|
+
);
|
|
111
|
+
expect(assertNotificationRoutes(eventNotificationRoutes('wireguard-server-down', CONF))).to.have.lengthOf(1);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('mailer send middleware', () => {
|
|
116
|
+
it('wraps a delivery in registration order and unregisters on dispose', async () => {
|
|
117
|
+
const provider = await loadedProviderFactory();
|
|
118
|
+
const order = [];
|
|
119
|
+
const dispose = provider.use(async (context, next) => {
|
|
120
|
+
order.push(`outer:${context.id}`);
|
|
121
|
+
return await next();
|
|
122
|
+
});
|
|
123
|
+
// Suppressing the transport keeps the assertion on ordering, not on SMTP.
|
|
124
|
+
provider.use(async () => {
|
|
125
|
+
order.push('inner');
|
|
126
|
+
return { messageId: 'stub' };
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const info = await provider.send({ id: 'test', sendOptions: { to: 'a@b.com', subject: 'hi', text: 'hi' } });
|
|
130
|
+
expect(info).to.deep.equal({ messageId: 'stub' });
|
|
131
|
+
expect(order).to.deep.equal(['outer:test', 'inner']);
|
|
132
|
+
|
|
133
|
+
dispose();
|
|
134
|
+
order.length = 0;
|
|
135
|
+
await provider.send({ id: 'test', sendOptions: { to: 'a@b.com', subject: 'hi', text: 'hi' } });
|
|
136
|
+
expect(order).to.deep.equal(['inner']);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('defaults the sender before any middleware observes the message', async () => {
|
|
140
|
+
const provider = await loadedProviderFactory();
|
|
141
|
+
let observed;
|
|
142
|
+
provider.use(async (context) => {
|
|
143
|
+
observed = context.sendOptions.from;
|
|
144
|
+
return { messageId: 'stub' };
|
|
145
|
+
});
|
|
146
|
+
await provider.send({ id: 'test', sendOptions: { to: 'a@b.com', subject: 'hi', text: 'hi' } });
|
|
147
|
+
expect(observed).to.equal('Sender <sender@example.com>');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('mailer interceptor', () => {
|
|
152
|
+
it('records what was sent and waits for a specific message', async () => {
|
|
153
|
+
const provider = await loadedProviderFactory();
|
|
154
|
+
const interceptor = mailerInterceptorFactory({ provider, suppress: true });
|
|
155
|
+
|
|
156
|
+
const pending = interceptor.waitFor((message) => message.sendOptions.subject.includes('wireguard-server-down'), {
|
|
157
|
+
timeoutMs: 2000,
|
|
158
|
+
intervalMs: 10,
|
|
159
|
+
});
|
|
160
|
+
await provider.send({
|
|
161
|
+
id: 'test',
|
|
162
|
+
sendOptions: { to: 'ops@example.com', subject: '[underpost] wireguard-server-down — hub — remediated', text: '' },
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const message = await pending;
|
|
166
|
+
expect(message.accepted).to.equal(true);
|
|
167
|
+
expect(message.sendOptions.to).to.equal('ops@example.com');
|
|
168
|
+
expect(interceptor.messages).to.have.lengthOf(1);
|
|
169
|
+
|
|
170
|
+
interceptor.close();
|
|
171
|
+
provider.use(async () => ({ messageId: 'stub' }));
|
|
172
|
+
await provider.send({ id: 'test', sendOptions: { to: 'ops@example.com', subject: 'later', text: '' } });
|
|
173
|
+
expect(interceptor.messages).to.have.lengthOf(1);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('resolves undefined when nothing matching is ever sent', async () => {
|
|
177
|
+
const provider = await loadedProviderFactory();
|
|
178
|
+
const interceptor = mailerInterceptorFactory({ provider, suppress: true });
|
|
179
|
+
const message = await interceptor.waitFor(() => false, { timeoutMs: 60, intervalMs: 10 });
|
|
180
|
+
interceptor.close();
|
|
181
|
+
expect(message).to.equal(undefined);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('mailer transport lifecycle', () => {
|
|
186
|
+
it('releases the instance so a one-shot process can exit', async () => {
|
|
187
|
+
const provider = await loadedProviderFactory();
|
|
188
|
+
expect(provider.instance.test).to.be.an('object');
|
|
189
|
+
expect(provider.close('test')).to.equal(true);
|
|
190
|
+
expect(provider.instance.test).to.equal(undefined);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('is a no-op for an instance that was never loaded', async () => {
|
|
194
|
+
const provider = await loadedProviderFactory();
|
|
195
|
+
expect(provider.close('absent')).to.equal(false);
|
|
196
|
+
});
|
|
197
|
+
});
|