cyberia 3.2.12 → 3.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.github/workflows/engine-cyberia.cd.yml +1 -0
  2. package/.github/workflows/engine-cyberia.ci.yml +14 -2
  3. package/.github/workflows/ghpkg.ci.yml +1 -0
  4. package/.github/workflows/npmpkg.ci.yml +9 -5
  5. package/CHANGELOG.md +151 -1
  6. package/CLI-HELP.md +975 -1130
  7. package/bin/build.js +97 -136
  8. package/bin/build.template.js +25 -179
  9. package/bin/cyberia.js +11 -6
  10. package/bin/deploy.js +4 -1
  11. package/bin/index.js +11 -6
  12. package/conf.js +1 -0
  13. package/deployment.yaml +74 -2
  14. package/hardhat/package-lock.json +4 -4
  15. package/hardhat/package.json +1 -1
  16. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
  17. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  18. package/manifests/deployment/dd-cyberia-development/deployment.yaml +74 -2
  19. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  20. package/package.json +7 -7
  21. package/scripts/link-local-underpost-cli.sh +6 -0
  22. package/scripts/test-monitor.sh +250 -0
  23. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +7 -0
  24. package/src/cli/deploy.js +200 -282
  25. package/src/cli/env.js +1 -4
  26. package/src/cli/image.js +58 -4
  27. package/src/cli/index.js +47 -0
  28. package/src/cli/monitor.js +387 -6
  29. package/src/cli/release.js +26 -11
  30. package/src/cli/repository.js +101 -7
  31. package/src/cli/run.js +159 -73
  32. package/src/client/components/core/PanelForm.js +44 -44
  33. package/src/client/components/cyberia/SharedDefaultsCyberia.js +1 -1
  34. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +55 -1
  35. package/src/client/public/cyberia-docs/ARCHITECTURE.md +272 -50
  36. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +20 -11
  37. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +23 -1
  38. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  39. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  40. package/src/db/mongo/MongooseDB.js +2 -1
  41. package/src/index.js +1 -1
  42. package/src/runtime/cyberia-client/Dockerfile +4 -22
  43. package/src/runtime/cyberia-client/Dockerfile.dev +3 -18
  44. package/src/runtime/cyberia-server/Dockerfile +3 -23
  45. package/src/runtime/cyberia-server/Dockerfile.dev +3 -27
  46. package/src/runtime/wp/Dockerfile +3 -3
  47. package/src/server/catalog-underpost.js +61 -0
  48. package/src/server/catalog.js +77 -0
  49. package/src/server/conf.js +414 -56
  50. package/src/server/ipfs-client.js +5 -3
  51. package/src/server/runtime-status.js +235 -0
  52. package/src/server/start.js +32 -11
  53. package/test/deploy-monitor.test.js +251 -0
  54. package/manifests/deployment/dd-test-development/deployment.yaml +0 -256
  55. package/manifests/deployment/dd-test-development/proxy.yaml +0 -102
package/deployment.yaml CHANGED
@@ -20,11 +20,14 @@ spec:
20
20
  spec:
21
21
  containers:
22
22
  - name: dd-cyberia-development-blue
23
- image: underpost/underpost-engine:v3.2.12
23
+ image: underpost/underpost-engine:v3.2.22
24
24
  imagePullPolicy: IfNotPresent
25
25
  envFrom:
26
26
  - secretRef:
27
27
  name: underpost-config
28
+ env:
29
+ - name: UNDERPOST_INTERNAL_PORT
30
+ value: "4004"
28
31
 
29
32
  command:
30
33
  - /bin/sh
@@ -32,6 +35,39 @@ spec:
32
35
  - >
33
36
  underpost secret underpost --create-from-env &&
34
37
  underpost start --build --run dd-cyberia development
38
+ readinessProbe:
39
+ {
40
+ "httpGet": {
41
+ "path": "/_internal/ready",
42
+ "port": 4004
43
+ },
44
+ "initialDelaySeconds": 5,
45
+ "periodSeconds": 5,
46
+ "timeoutSeconds": 3,
47
+ "failureThreshold": 3
48
+ }
49
+ livenessProbe:
50
+ {
51
+ "httpGet": {
52
+ "path": "/_internal/health",
53
+ "port": 4004
54
+ },
55
+ "initialDelaySeconds": 30,
56
+ "periodSeconds": 15,
57
+ "timeoutSeconds": 3,
58
+ "failureThreshold": 3
59
+ }
60
+ startupProbe:
61
+ {
62
+ "httpGet": {
63
+ "path": "/_internal/ready",
64
+ "port": 4004
65
+ },
66
+ "initialDelaySeconds": 10,
67
+ "periodSeconds": 10,
68
+ "timeoutSeconds": 3,
69
+ "failureThreshold": 180
70
+ }
35
71
 
36
72
 
37
73
 
@@ -193,11 +229,14 @@ spec:
193
229
  spec:
194
230
  containers:
195
231
  - name: dd-cyberia-development-green
196
- image: underpost/underpost-engine:v3.2.12
232
+ image: underpost/underpost-engine:v3.2.22
197
233
  imagePullPolicy: IfNotPresent
198
234
  envFrom:
199
235
  - secretRef:
200
236
  name: underpost-config
237
+ env:
238
+ - name: UNDERPOST_INTERNAL_PORT
239
+ value: "4004"
201
240
 
202
241
  command:
203
242
  - /bin/sh
@@ -205,6 +244,39 @@ spec:
205
244
  - >
206
245
  underpost secret underpost --create-from-env &&
207
246
  underpost start --build --run dd-cyberia development
247
+ readinessProbe:
248
+ {
249
+ "httpGet": {
250
+ "path": "/_internal/ready",
251
+ "port": 4004
252
+ },
253
+ "initialDelaySeconds": 5,
254
+ "periodSeconds": 5,
255
+ "timeoutSeconds": 3,
256
+ "failureThreshold": 3
257
+ }
258
+ livenessProbe:
259
+ {
260
+ "httpGet": {
261
+ "path": "/_internal/health",
262
+ "port": 4004
263
+ },
264
+ "initialDelaySeconds": 30,
265
+ "periodSeconds": 15,
266
+ "timeoutSeconds": 3,
267
+ "failureThreshold": 3
268
+ }
269
+ startupProbe:
270
+ {
271
+ "httpGet": {
272
+ "path": "/_internal/ready",
273
+ "port": 4004
274
+ },
275
+ "initialDelaySeconds": 10,
276
+ "periodSeconds": 10,
277
+ "timeoutSeconds": 3,
278
+ "failureThreshold": 180
279
+ }
208
280
 
209
281
 
210
282
 
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "@nomicfoundation/hardhat-toolbox-mocha-ethers": "~3.0.6",
17
- "hardhat": "~3.6.0"
17
+ "hardhat": "~3.7.0"
18
18
  },
19
19
  "engines": {
20
20
  "node": ">=22.0.0"
@@ -2593,9 +2593,9 @@
2593
2593
  "license": "ISC"
2594
2594
  },
2595
2595
  "node_modules/hardhat": {
2596
- "version": "3.6.0",
2597
- "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-3.6.0.tgz",
2598
- "integrity": "sha512-6bYQk+UYdi4b/syTLYgsdAa3Mll0kaRdY2kJOylsaup/20f9gYM9+c3xmK2eCgW1wvmXSwKZTNaVDzDiNtK53Q==",
2596
+ "version": "3.7.0",
2597
+ "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-3.7.0.tgz",
2598
+ "integrity": "sha512-dbz5wbN7sTkTjUicCX1qSAwrBQBklEl+j5gjiykzQa9JZx/RZ9OtlY9SvOOEV/2IrlgKhUqy30nGCU9MtOObSw==",
2599
2599
  "dev": true,
2600
2600
  "license": "MIT",
2601
2601
  "dependencies": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "devDependencies": {
19
19
  "@nomicfoundation/hardhat-toolbox-mocha-ethers": "~3.0.6",
20
- "hardhat": "~3.6.0"
20
+ "hardhat": "~3.7.0"
21
21
  },
22
22
  "dependencies": {
23
23
  "@openzeppelin/contracts": "~5.6.1",
@@ -23,14 +23,14 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-backup
26
- image: underpost/underpost-engine:v3.2.12
26
+ image: underpost/underpost-engine:v3.2.22
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
30
30
  - >
31
31
  cd /home/dd/engine &&
32
32
  node bin env dd-cron production &&
33
- node bin cron dd-lampp,dd-cyberia,dd-core,dd-test backup --git --kubeadm
33
+ node bin cron dd-lampp,dd-cyberia,dd-core,dd-prototype,dd-test backup --git --kubeadm
34
34
  volumeMounts:
35
35
  - mountPath: /home/dd/engine
36
36
  name: underpost-cron-container-volume
@@ -23,7 +23,7 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-dns
26
- image: underpost/underpost-engine:v3.2.12
26
+ image: underpost/underpost-engine:v3.2.22
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
@@ -20,11 +20,14 @@ spec:
20
20
  spec:
21
21
  containers:
22
22
  - name: dd-cyberia-development-blue
23
- image: underpost/underpost-engine:v3.2.12
23
+ image: underpost/underpost-engine:v3.2.22
24
24
  imagePullPolicy: IfNotPresent
25
25
  envFrom:
26
26
  - secretRef:
27
27
  name: underpost-config
28
+ env:
29
+ - name: UNDERPOST_INTERNAL_PORT
30
+ value: "4004"
28
31
 
29
32
  command:
30
33
  - /bin/sh
@@ -32,6 +35,39 @@ spec:
32
35
  - >
33
36
  underpost secret underpost --create-from-env &&
34
37
  underpost start --build --run dd-cyberia development
38
+ readinessProbe:
39
+ {
40
+ "httpGet": {
41
+ "path": "/_internal/ready",
42
+ "port": 4004
43
+ },
44
+ "initialDelaySeconds": 5,
45
+ "periodSeconds": 5,
46
+ "timeoutSeconds": 3,
47
+ "failureThreshold": 3
48
+ }
49
+ livenessProbe:
50
+ {
51
+ "httpGet": {
52
+ "path": "/_internal/health",
53
+ "port": 4004
54
+ },
55
+ "initialDelaySeconds": 30,
56
+ "periodSeconds": 15,
57
+ "timeoutSeconds": 3,
58
+ "failureThreshold": 3
59
+ }
60
+ startupProbe:
61
+ {
62
+ "httpGet": {
63
+ "path": "/_internal/ready",
64
+ "port": 4004
65
+ },
66
+ "initialDelaySeconds": 10,
67
+ "periodSeconds": 10,
68
+ "timeoutSeconds": 3,
69
+ "failureThreshold": 180
70
+ }
35
71
 
36
72
 
37
73
 
@@ -193,11 +229,14 @@ spec:
193
229
  spec:
194
230
  containers:
195
231
  - name: dd-cyberia-development-green
196
- image: underpost/underpost-engine:v3.2.12
232
+ image: underpost/underpost-engine:v3.2.22
197
233
  imagePullPolicy: IfNotPresent
198
234
  envFrom:
199
235
  - secretRef:
200
236
  name: underpost-config
237
+ env:
238
+ - name: UNDERPOST_INTERNAL_PORT
239
+ value: "4004"
201
240
 
202
241
  command:
203
242
  - /bin/sh
@@ -205,6 +244,39 @@ spec:
205
244
  - >
206
245
  underpost secret underpost --create-from-env &&
207
246
  underpost start --build --run dd-cyberia development
247
+ readinessProbe:
248
+ {
249
+ "httpGet": {
250
+ "path": "/_internal/ready",
251
+ "port": 4004
252
+ },
253
+ "initialDelaySeconds": 5,
254
+ "periodSeconds": 5,
255
+ "timeoutSeconds": 3,
256
+ "failureThreshold": 3
257
+ }
258
+ livenessProbe:
259
+ {
260
+ "httpGet": {
261
+ "path": "/_internal/health",
262
+ "port": 4004
263
+ },
264
+ "initialDelaySeconds": 30,
265
+ "periodSeconds": 15,
266
+ "timeoutSeconds": 3,
267
+ "failureThreshold": 3
268
+ }
269
+ startupProbe:
270
+ {
271
+ "httpGet": {
272
+ "path": "/_internal/ready",
273
+ "port": 4004
274
+ },
275
+ "initialDelaySeconds": 10,
276
+ "periodSeconds": 10,
277
+ "timeoutSeconds": 3,
278
+ "failureThreshold": 180
279
+ }
208
280
 
209
281
 
210
282
 
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: underpost/underpost-engine:v3.2.12
20
+ image: underpost/underpost-engine:v3.2.22
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -98,7 +98,7 @@ spec:
98
98
  spec:
99
99
  containers:
100
100
  - name: dd-default-development-green
101
- image: underpost/underpost-engine:v3.2.12
101
+ image: underpost/underpost-engine:v3.2.22
102
102
  # resources:
103
103
  # requests:
104
104
  # memory: "124Ki"
package/package.json CHANGED
@@ -2,12 +2,13 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "cyberia",
5
- "version": "3.2.12",
5
+ "version": "3.2.22",
6
6
  "description": "Cyberia CLI — toolchain for the Cyberia MMO data layer, content pipeline, persistence, gRPC services, and ERC-1155 lifecycle on Hyperledger Besu.",
7
7
  "scripts": {
8
8
  "start": "node --max-old-space-size=8192 src/server",
9
9
  "build": "node bin client",
10
10
  "test": "NODE_ENV=test c8 mocha",
11
+ "test:monitor": "NODE_ENV=test c8 mocha test/deploy-monitor.test.js",
11
12
  "dev": "NODE_ENV=development nodemon src/server",
12
13
  "dev:container": "NODE_ENV=development node src/server",
13
14
  "prod:container": "NODE_ENV=production node src/server",
@@ -40,7 +41,6 @@
40
41
  "engine-cyberia",
41
42
  "sidecar",
42
43
  "data-layer",
43
- "engine-cyberia",
44
44
  "object-layer",
45
45
  "atlas-sprite-sheet",
46
46
  "ipfs",
@@ -73,12 +73,12 @@
73
73
  "clipboardy": "^5.3.1",
74
74
  "cloudinary": "^2.10.0",
75
75
  "colors": "^1.4.0",
76
- "commander": "^14.0.3",
76
+ "commander": "^15.0.0",
77
77
  "compression": "^1.7.4",
78
78
  "cookie-parser": "^1.4.7",
79
79
  "cors": "^2.8.6",
80
80
  "d3": "^7.9.0",
81
- "dexie": "^4.2.1",
81
+ "dexie": "^4.4.3",
82
82
  "dotenv": "^17.4.2",
83
83
  "easymde": "^2.21.0",
84
84
  "esbuild": "^0.28.0",
@@ -88,7 +88,7 @@
88
88
  "express-rate-limit": "^8.5.2",
89
89
  "express-slow-down": "^3.1.0",
90
90
  "fast-json-stable-stringify": "^2.1.0",
91
- "favicons": "^7.2.0",
91
+ "favicons": "^7.3.0",
92
92
  "fs-extra": "^11.3.5",
93
93
  "fullcalendar": "^6.1.15",
94
94
  "helmet": "^8.2.0",
@@ -101,9 +101,9 @@
101
101
  "mariadb": "^3.2.2",
102
102
  "mocha": "^11.7.6",
103
103
  "marked": "^18.0.4",
104
- "mongoose": "^9.6.2",
104
+ "mongoose": "^9.6.3",
105
105
  "morgan": "^1.10.0",
106
- "nodemailer": "^8.0.9",
106
+ "nodemailer": "^8.0.10",
107
107
  "nodemon": "^3.0.1",
108
108
  "peer": "^1.0.2",
109
109
  "peerjs": "^1.5.5",
@@ -0,0 +1,6 @@
1
+
2
+ #!/usr/bin/env bash
3
+ set -euo pipefail
4
+
5
+ cd /home/dd && underpost clone underpostnet/pwa-microservices-template
6
+ cd /home/dd/pwa-microservices-template && npm install && npm link
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # test-monitor.sh — end-to-end deploy + two-phase monitor smoke test.
4
+ #
5
+ # Two deployment shapes are supported (see
6
+ # src/client/public/nexodev/docs/references/Deploy-Monitor-PRD.md and
7
+ # 'Deploy custom instance to K8S.md'):
8
+ #
9
+ # --mode runtime `underpost start` deploy (e.g. dd-test). Monitored with the
10
+ # HTTP gate: /_internal/ready probes + port-forward status.
11
+ # --mode instance Custom instances from conf.instances.json (e.g. cyberia
12
+ # mmo-server / mmo-client). Monitored with the kubernetes gate
13
+ # (TCP readinessProbe) + exec status transport.
14
+ #
15
+ # Every variable in the DEFAULTS block below is overridable with a flag of the
16
+ # same name (--env, --deploy-id, …). Run with --help for the full list.
17
+ #
18
+ set -euo pipefail
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+ ENGINE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
22
+ cd "$ENGINE_DIR"
23
+
24
+ # ─────────────────────────── DEFAULTS (all overridable) ───────────────────────────
25
+ MODE=runtime # runtime | instance
26
+ ENV=development # development | production
27
+ DEPLOY_ID=dd-test # deploy id (instance mode: parent of conf.instances.json)
28
+ INSTANCE_IDS= # instance mode: csv of ids (default: all in conf.instances.json)
29
+ IMAGE=underpost/wp:v3.2.14 # runtime mode image (instance mode reads image from conf)
30
+ VERSIONS=green # csv of blue/green versions
31
+ REPLICAS=1 # replicas per deployment
32
+ NAMESPACE=default # k8s namespace
33
+ CLUSTER= # kind | kubeadm | k3s | "" (auto/none)
34
+ TIMEOUT_RESPONSE=300000ms # HTTPProxy per-route response timeout
35
+ TEMPLATE_REPO=underpostnet/pwa-microservices-template-private # runtime mode link repo
36
+ ENVOY_NAMESPACE=projectcontour # ingress namespace (instance TLS exposure)
37
+ ENVOY_SERVICE=envoy # ingress service (instance TLS exposure)
38
+ HTTPS_PORT=443 # local https port for instance TLS exposure
39
+
40
+ USE_CERT=false # runtime: pass --cert to the proxy step
41
+ USE_PULL_BUNDLE=false # runtime: include --pull-bundle in the start cmd
42
+ USE_TLS=false # generate self-signed certs + expose over HTTPS
43
+ USE_TEST_REPO=false # runtime: publish src to engine-test-<id> + pod clones it (--private-test-repo)
44
+ DO_BUILD_TEMPLATE=true # run `node bin/build.template --update-private`
45
+ DO_CLUSTER_MANIFESTS=true # run `node bin run build-cluster-deployment-manifests`
46
+ DO_EXPOSE=true # expose locally after deploy + monitor
47
+
48
+ usage() {
49
+ cat <<'EOF'
50
+ Usage: scripts/test-monitor.sh [flags]
51
+
52
+ Modes:
53
+ --mode <runtime|instance> Deployment shape to test (default: runtime)
54
+
55
+ Common (every default is overridable):
56
+ --env <development|production>
57
+ --deploy-id <id>
58
+ --instance-ids <csv> instance mode only; default = all ids in conf.instances.json
59
+ --image <image> runtime mode only
60
+ --versions <csv> e.g. green or blue,green
61
+ --replicas <n>
62
+ --namespace <ns>
63
+ --cluster <kind|kubeadm|k3s|none>
64
+ --timeout-response <dur> e.g. 300000ms
65
+ --template-repo <owner/repo> runtime mode link repo
66
+ --envoy-namespace <ns> instance TLS exposure ingress namespace
67
+ --envoy-service <name> instance TLS exposure ingress service
68
+ --https-port <port> local https port for instance TLS exposure
69
+
70
+ Toggles (use --x / --no-x):
71
+ --tls | --no-tls self-signed certs + HTTPS exposure (default: off)
72
+ --cert | --no-cert runtime proxy --cert (default: off)
73
+ --pull-bundle | --no-pull-bundle runtime start --pull-bundle (default: off)
74
+ --test-repo | --no-test-repo runtime: publish src to engine-test-<id> and have the
75
+ pod clone it via --private-test-repo (default: off)
76
+ --expose | --no-expose local exposure after monitor (default: on)
77
+ --build-template | --no-build-template sync private template (default: on)
78
+ --cluster-manifests | --no-cluster-manifests rebuild cluster manifests (default: on)
79
+
80
+ -h, --help
81
+
82
+ Examples:
83
+ # Runtime deploy (default), no TLS
84
+ scripts/test-monitor.sh
85
+
86
+ # Runtime deploy over HTTPS
87
+ scripts/test-monitor.sh --tls
88
+
89
+ # Runtime deploy from a work-in-progress test source repo (engine-test-<id>)
90
+ scripts/test-monitor.sh --test-repo
91
+
92
+ # Cyberia instances (both), dev on kind, no TLS
93
+ scripts/test-monitor.sh --mode instance --deploy-id dd-cyberia --cluster kind
94
+
95
+ # Only the mmo-server instance, production, over HTTPS
96
+ scripts/test-monitor.sh --mode instance --deploy-id dd-cyberia \
97
+ --instance-ids mmo-server --env production --cluster kubeadm --tls
98
+ EOF
99
+ }
100
+
101
+ # ─────────────────────────── flag parsing ───────────────────────────
102
+ # Supports `--key value` and `--key=value` for value flags, plus --x/--no-x toggles.
103
+ needval() { [[ $# -ge 2 ]] || { echo "Missing value for $1" >&2; exit 1; }; }
104
+ while [[ $# -gt 0 ]]; do
105
+ case "$1" in
106
+ --mode) needval "$@"; MODE="$2"; shift 2;; --mode=*) MODE="${1#*=}"; shift;;
107
+ --env) needval "$@"; ENV="$2"; shift 2;; --env=*) ENV="${1#*=}"; shift;;
108
+ --deploy-id) needval "$@"; DEPLOY_ID="$2"; shift 2;; --deploy-id=*) DEPLOY_ID="${1#*=}"; shift;;
109
+ --instance-ids) needval "$@"; INSTANCE_IDS="$2"; shift 2;; --instance-ids=*) INSTANCE_IDS="${1#*=}"; shift;;
110
+ --image) needval "$@"; IMAGE="$2"; shift 2;; --image=*) IMAGE="${1#*=}"; shift;;
111
+ --versions) needval "$@"; VERSIONS="$2"; shift 2;; --versions=*) VERSIONS="${1#*=}"; shift;;
112
+ --replicas) needval "$@"; REPLICAS="$2"; shift 2;; --replicas=*) REPLICAS="${1#*=}"; shift;;
113
+ --namespace) needval "$@"; NAMESPACE="$2"; shift 2;; --namespace=*) NAMESPACE="${1#*=}"; shift;;
114
+ --cluster) needval "$@"; CLUSTER="$2"; shift 2;; --cluster=*) CLUSTER="${1#*=}"; shift;;
115
+ --timeout-response) needval "$@"; TIMEOUT_RESPONSE="$2"; shift 2;; --timeout-response=*) TIMEOUT_RESPONSE="${1#*=}"; shift;;
116
+ --template-repo) needval "$@"; TEMPLATE_REPO="$2"; shift 2;; --template-repo=*) TEMPLATE_REPO="${1#*=}"; shift;;
117
+ --envoy-namespace) needval "$@"; ENVOY_NAMESPACE="$2"; shift 2;; --envoy-namespace=*) ENVOY_NAMESPACE="${1#*=}"; shift;;
118
+ --envoy-service) needval "$@"; ENVOY_SERVICE="$2"; shift 2;; --envoy-service=*) ENVOY_SERVICE="${1#*=}"; shift;;
119
+ --https-port) needval "$@"; HTTPS_PORT="$2"; shift 2;; --https-port=*) HTTPS_PORT="${1#*=}"; shift;;
120
+ --tls) USE_TLS=true; shift;; --no-tls) USE_TLS=false; shift;;
121
+ --cert) USE_CERT=true; shift;; --no-cert) USE_CERT=false; shift;;
122
+ --pull-bundle) USE_PULL_BUNDLE=true; shift;; --no-pull-bundle) USE_PULL_BUNDLE=false; shift;;
123
+ --test-repo) USE_TEST_REPO=true; shift;; --no-test-repo) USE_TEST_REPO=false; shift;;
124
+ --expose) DO_EXPOSE=true; shift;; --no-expose) DO_EXPOSE=false; shift;;
125
+ --build-template) DO_BUILD_TEMPLATE=true; shift;; --no-build-template) DO_BUILD_TEMPLATE=false; shift;;
126
+ --cluster-manifests) DO_CLUSTER_MANIFESTS=true; shift;; --no-cluster-manifests) DO_CLUSTER_MANIFESTS=false; shift;;
127
+ -h|--help) usage; exit 0;;
128
+ *) echo "Unknown flag: $1" >&2; usage; exit 1;;
129
+ esac
130
+ done
131
+
132
+ # ─────────────────────────── derived flags ───────────────────────────
133
+ CLUSTER_FLAG=""
134
+ case "$CLUSTER" in
135
+ kind) CLUSTER_FLAG="--kind";;
136
+ kubeadm) CLUSTER_FLAG="--kubeadm";;
137
+ k3s) CLUSTER_FLAG="--k3s";;
138
+ ""|none) CLUSTER_FLAG="";;
139
+ *) echo "Unknown --cluster: $CLUSTER (expected kind|kubeadm|k3s|none)" >&2; exit 1;;
140
+ esac
141
+ DEV_FLAG=""; [ "$ENV" = development ] && DEV_FLAG="--dev"
142
+ INSTANCES_CONF="./engine-private/conf/${DEPLOY_ID}/conf.instances.json"
143
+ SERVER_CONF="./engine-private/conf/${DEPLOY_ID}/conf.server.json"
144
+
145
+ echo "[test-monitor] mode=$MODE env=$ENV deploy=$DEPLOY_ID cluster=${CLUSTER:-none} tls=$USE_TLS test-repo=$USE_TEST_REPO expose=$DO_EXPOSE"
146
+
147
+ # ─────────────────────────── shared helpers ───────────────────────────
148
+
149
+ # setup_tls_secrets <host> [<host> …] — regenerate self-signed certs and create
150
+ # the per-host k8s TLS secret the HTTPProxy references (name == host).
151
+ setup_tls_secrets() {
152
+ local ssl_base="${ENGINE_DIR}/engine-private/ssl"
153
+ for host in "$@"; do
154
+ local cert_dir="${ssl_base}/${host}"
155
+ mkdir -p "$cert_dir"
156
+ bash "${SCRIPT_DIR}/ssl.sh" "$cert_dir" "$host"
157
+ local name_safe="${host//[^a-zA-Z0-9_.-]/_}"
158
+ kubectl delete secret "$host" -n "$NAMESPACE" --ignore-not-found
159
+ kubectl create secret tls "$host" \
160
+ --cert="${cert_dir}/${name_safe}.pem" \
161
+ --key="${cert_dir}/${name_safe}-key.pem" \
162
+ -n "$NAMESPACE"
163
+ done
164
+ }
165
+
166
+ # hosts_from <conf.json> — unique hosts declared in a conf.server.json or conf.instances.json.
167
+ hosts_from() {
168
+ node -e "
169
+ const c = require('$1');
170
+ const hosts = Array.isArray(c) ? c.map(i => i.host) : Object.keys(c);
171
+ console.log([...new Set(hosts)].join(' '));
172
+ "
173
+ }
174
+
175
+ # ─────────────────────────── pre-steps ───────────────────────────
176
+ [ "$DO_CLUSTER_MANIFESTS" = true ] && node bin run build-cluster-deployment-manifests
177
+ [ "$DO_BUILD_TEMPLATE" = true ] && node bin/build.template --update-private
178
+
179
+ # ─────────────────────────── runtime mode ───────────────────────────
180
+ run_runtime_mode() {
181
+ local link_cmd="cd /home/dd,underpost clone ${TEMPLATE_REPO},cd /home/dd/${TEMPLATE_REPO##*/},npm install,npm link"
182
+ local deploy_cmd proxy_flag="" expose_flags="" start_flags=""
183
+
184
+ # Publish the local engine src to underpostnet/engine-test-<id> so the pod
185
+ # (started with --private-test-repo) clones this work-in-progress source.
186
+ [ "$USE_TEST_REPO" = true ] && node bin/build "$DEPLOY_ID" --update-private
187
+
188
+ [ "$USE_PULL_BUNDLE" = true ] && start_flags="${start_flags} --pull-bundle"
189
+ [ "$USE_TEST_REPO" = true ] && start_flags="${start_flags} --private-test-repo"
190
+ deploy_cmd="${link_cmd},underpost start --build --run${start_flags} ${DEPLOY_ID} ${ENV}"
191
+
192
+ [ "$USE_CERT" = true ] && proxy_flag="--cert"
193
+ [ "$USE_TLS" = true ] && proxy_flag="--self-signed"
194
+
195
+ node bin deploy "$DEPLOY_ID" "$ENV" $CLUSTER_FLAG --sync --build-manifest \
196
+ --image "$IMAGE" --timeout-response "$TIMEOUT_RESPONSE" --versions "$VERSIONS" --replicas "$REPLICAS" --cmd "$deploy_cmd"
197
+ node bin deploy "$DEPLOY_ID" "$ENV" $CLUSTER_FLAG --disable-update-proxy $proxy_flag
198
+ node bin monitor "$DEPLOY_ID" "$ENV" --ready-deployment --promote \
199
+ --timeout-response "$TIMEOUT_RESPONSE" --versions "$VERSIONS" --replicas "$REPLICAS"
200
+
201
+ node bin run etc-hosts --deploy-id "$DEPLOY_ID"
202
+
203
+ if [ "$USE_TLS" = true ]; then
204
+ setup_tls_secrets $(hosts_from "$SERVER_CONF")
205
+ expose_flags="--tls"
206
+ fi
207
+ [ "$DO_EXPOSE" = true ] && node bin deploy --expose --local-proxy "$DEPLOY_ID" "$ENV" $expose_flags
208
+ }
209
+
210
+ # ─────────────────────────── instance mode ───────────────────────────
211
+ run_instance_mode() {
212
+ [ -f "$INSTANCES_CONF" ] || { echo "Missing $INSTANCES_CONF" >&2; exit 1; }
213
+ if [ -z "$INSTANCE_IDS" ]; then
214
+ INSTANCE_IDS=$(node -e "console.log(require('$INSTANCES_CONF').map(i=>i.id).join(','))")
215
+ fi
216
+ local tls_flag=""; [ "$USE_TLS" = true ] && tls_flag="--tls --test"
217
+
218
+ # `run instance` builds/pulls the image, applies the manifest, monitors with the
219
+ # kubernetes gate (TCP readinessProbe) + exec status, then promotes traffic.
220
+ IFS=',' read -ra ids <<< "$INSTANCE_IDS"
221
+ for id in "${ids[@]}"; do
222
+ [ -n "$id" ] || continue
223
+ echo "[test-monitor] deploying instance ${DEPLOY_ID},${id}"
224
+ node bin run instance "${DEPLOY_ID},${id},${REPLICAS}" \
225
+ $DEV_FLAG $CLUSTER_FLAG --namespace "$NAMESPACE" --etc-hosts $tls_flag \
226
+ ${IMAGE:+--image-name "$IMAGE"}
227
+ done
228
+
229
+ [ "$DO_EXPOSE" = true ] || return 0
230
+ if [ "$USE_TLS" = true ]; then
231
+ # Instances are routed by the Contour ingress; port-forward Envoy so the
232
+ # HTTPProxy host routing (server/client.cyberiaonline.com) works locally.
233
+ echo "[test-monitor] exposing HTTPS via ${ENVOY_NAMESPACE}/${ENVOY_SERVICE} on :${HTTPS_PORT}"
234
+ sudo kubectl port-forward -n "$ENVOY_NAMESPACE" "svc/${ENVOY_SERVICE}" "${HTTPS_PORT}:443" &
235
+ else
236
+ # Plain HTTP: port-forward each instance service port directly.
237
+ for id in "${ids[@]}"; do
238
+ [ -n "$id" ] || continue
239
+ node bin deploy --expose "${DEPLOY_ID}-${id}" "$ENV" --namespace "$NAMESPACE" || true
240
+ done
241
+ fi
242
+ }
243
+
244
+ case "$MODE" in
245
+ runtime) run_runtime_mode;;
246
+ instance) run_instance_mode;;
247
+ *) echo "Unknown --mode: $MODE (expected runtime|instance)" >&2; exit 1;;
248
+ esac
249
+
250
+ echo "[test-monitor] done (mode=$MODE tls=$USE_TLS)"
@@ -117,6 +117,8 @@ export const DefaultCyberiaDialogues = [
117
117
  { code: 'quest-talk-wason', order: 2, speaker: 'Wason', text: 'And one more thing: the SCP-2040 anomalies are overrunning my trade routes. Deal with two of them.', mood: 'sad' },
118
118
  { code: 'quest-talk-alex', order: 0, speaker: 'Alex', text: "Wason sent you? Good. The portal anomalies are getting worse. I've logged what I can.", mood: 'neutral' },
119
119
  { code: 'quest-talk-alex', order: 1, speaker: 'Alex', text: 'Tell Wason: the source is somewhere in the deeper nodes. The registry does not lie.', mood: 'neutral' },
120
+ { code: 'talk-lain', order: 0, speaker: 'Lain', text: 'Present day... present time. You are here, so you are real.', mood: 'neutral' },
121
+ { code: 'talk-lain', order: 1, speaker: 'Lain', text: 'There is nothing I can grant you. Only the wired remembers.', mood: 'neutral' },
120
122
  ];
121
123
 
122
124
  /**
@@ -144,6 +146,11 @@ export const DefaultCyberiaActions = [
144
146
  provideItemId: 'wason', grantQuestCode: '',
145
147
  dialogCode: 'quest-talk-wason', questDialogueCodes: ['quest-talk-wason'],
146
148
  },
149
+ {
150
+ code: 'lain-talk', type: 'talk', label: 'Talk',
151
+ provideItemId: 'lain', grantQuestCode: '',
152
+ dialogCode: 'talk-lain', questDialogueCodes: ['talk-lain'],
153
+ },
147
154
  ];
148
155
 
149
156
  /**