unoverse 0.1.110 → 0.1.112

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.
@@ -0,0 +1,318 @@
1
+ # =============================================================================
2
+ # GRAVITY PLATFORM DOCKER COMPOSE
3
+ # =============================================================================
4
+ #
5
+ # LAYER 1: CORE PLATFORM (Pre-compiled via GitHub Actions → DOCR)
6
+ # - unoverse (the platform runtime — engine in-process + node plane + native MCP),
7
+ # canvas, umap, memory. Code protected, pulled as images.
8
+ #
9
+ # LAYER 2: PLATFORM-DEV MOUNTS (monorepo only — sync-starter strips them)
10
+ # - apps/unoverse/nodes — node manifests
11
+ # - apps/unoverse/rx — design (components, templates, styles)
12
+ # - apps/unoverse/prompts — behavior (skills + blocks)
13
+ # In a STARTER/customer universe these folders do not exist: authoring is
14
+ # Studio's (publish over the API) and content is DB-driven (marketplace).
15
+ # Everything else under apps/unoverse (engine, server, web, tools) is image-only.
16
+ #
17
+ # OBSERVABILITY (runs by default):
18
+ # - Dozzle — single-container live log viewer (http://localhost:8080)
19
+ #
20
+ # =============================================================================
21
+
22
+ # Bounds the disk Docker's json-file driver uses per container: rotate at 10 MB,
23
+ # keep 3 files → 30 MB ceiling each. Applied to every service via *default-logging.
24
+ # This is what caps log growth on the host (Dozzle just views it; it stores nothing).
25
+ x-logging: &default-logging
26
+ driver: json-file
27
+ options:
28
+ max-size: "10m"
29
+ max-file: "3"
30
+
31
+ services:
32
+ # ===========================================================================
33
+ # LAYER 1: CORE PLATFORM (DigitalOcean Container Registry)
34
+ # ===========================================================================
35
+ # Images pulled from: registry.digitalocean.com/gravity-repo/
36
+
37
+ # ═══════════════════════════════════════════════════════════════════════════
38
+ # RETIRED at the One Engine completion (ONE_ENGINE.md step 5): the gateway has
39
+ # zero jobs — the unoverse container serves /api, /ws/gravity, /components,
40
+ # and the Content Engine. ROLLBACK: uncomment this block and repoint the
41
+ # ingress api.{domain} target back to :4100. Image still published by CI.
42
+ # ═══════════════════════════════════════════════════════════════════════════
43
+ # server:
44
+ # image: registry.digitalocean.com/gravity-repo/server:latest
45
+ # ports:
46
+ # - "4100:4100"
47
+ # volumes:
48
+ # - ./packages/design-system:/app/packages/design-system
49
+ # environment:
50
+ # - NODE_ENV=production
51
+ # - PORT=4100
52
+ # - DESIGN_SYSTEM_PATH=/app/packages/design-system
53
+ # - REDIS_HOST=${REDIS_HOST:-}
54
+ # - REDIS_PORT=${REDIS_PORT:-}
55
+ # - REDIS_PASSWORD=${REDIS_PASSWORD:-}
56
+ # - REDIS_TLS=${REDIS_TLS:-}
57
+ # - REDIS_NAMESPACE=${REDIS_NAMESPACE:-}
58
+ # - AUTH_ISSUER=${AUTH_ISSUER:-}
59
+ # - AUTH_AUDIENCE=${AUTH_AUDIENCE:-}
60
+ # - WORKFLOW_SERVICE_URL=http://unoverse:4101
61
+ # - UNOVERSE_SERVICE_URL=http://unoverse:4106
62
+ # labels:
63
+ # - "com.docker.compose.service=server"
64
+ # restart: unless-stopped
65
+
66
+ # ═══════════════════════════════════════════════════════════════════════════
67
+ # RETIRED at the One Engine cutover (ONE_ENGINE.md step 5): the workflow engine
68
+ # now runs IN-PROCESS in the unoverse container, which serves the identical
69
+ # :4101 surface. ROLLBACK: uncomment this block, remove DATABASE_URL from the
70
+ # unoverse service (its capability gate — prevents double-boot), and point
71
+ # WORKFLOW_SERVICE_URL back to http://workflow:4101 everywhere. The
72
+ # gravity-workflow image is still published by CI for exactly this purpose.
73
+ # ═══════════════════════════════════════════════════════════════════════════
74
+ # workflow:
75
+ # image: registry.digitalocean.com/gravity-repo/workflow:latest
76
+ # ports:
77
+ # - "4101:4101"
78
+ # environment:
79
+ # - NODE_ENV=production
80
+ # - PORT=4101
81
+ # - REDIS_HOST=${REDIS_HOST:-}
82
+ # - REDIS_PORT=${REDIS_PORT:-}
83
+ # - REDIS_PASSWORD=${REDIS_PASSWORD:-}
84
+ # - REDIS_TLS=${REDIS_TLS:-}
85
+ # - REDIS_NAMESPACE=${REDIS_NAMESPACE:-}
86
+ # - DATABASE_URL=${DATABASE_URL:-}
87
+ # - SERVER_WS_URL=ws://server:4100
88
+ # - UMAP_SERVICE_URL=http://umap:5001
89
+ # - UNOVERSE_SERVICE_URL=http://unoverse:4106
90
+ # labels:
91
+ # - "com.docker.compose.service=workflow"
92
+ # depends_on:
93
+ # unoverse:
94
+ # condition: service_healthy
95
+ # restart: unless-stopped
96
+
97
+ # Canvas UI - React frontend (lightweight - static files via nginx)
98
+ # Runtime config injected via docker-entrypoint.sh at container start
99
+ canvas:
100
+ image: registry.digitalocean.com/gravity-repo/canvas:latest
101
+ ports:
102
+ - "3001:80"
103
+ environment:
104
+ - VITE_API_URL=${API_URL:-${DOMAIN:+https://api.${DOMAIN:-}}}
105
+ - VITE_SERVER_WS_URL=${VITE_SERVER_WS_URL:-${DOMAIN:+wss://api.${DOMAIN:-}}}
106
+ - VITE_AUTH_ISSUER=${AUTH_ISSUER:-}
107
+ - VITE_AUTH_CLIENT_ID=${AUTH_CLIENT_ID:-}
108
+ - VITE_AUTH_AUDIENCE=${AUTH_AUDIENCE:-}
109
+ # Unoverse public URL (JWT-gated :4105) — the browser calls it directly for
110
+ # component/template defs (MCP), prompt-blocks, and plugin management. This is the
111
+ # SAME :4105 backend as api.<domain>, so default to the api host (one public entry,
112
+ # one cert, no extra DNS). UNOVERSE_URL can still override for a dedicated MCP host.
113
+ - VITE_UNOVERSE_SERVICE_URL=${UNOVERSE_URL:-${DOMAIN:+https://api.${DOMAIN:-}}}
114
+ - MEMORY_SERVICE_URL=http://memory:4114
115
+ depends_on:
116
+ - unoverse
117
+ logging: *default-logging
118
+ restart: unless-stopped
119
+
120
+ # Studio is NOT a platform image (removed 2026-07-28): it ships from npm and
121
+ # connects to a universe over the API with a publish key.
122
+
123
+ # UMAP Service - Python ML service
124
+ umap:
125
+ image: registry.digitalocean.com/gravity-repo/umap:latest
126
+ ports:
127
+ - "5001:5001"
128
+ volumes:
129
+ - umap_models:/app/models
130
+ logging: *default-logging
131
+ restart: unless-stopped
132
+
133
+ # Unoverse - node plane (author·distribute·execute): the relocated node runtime +
134
+ # workbench + MCP. TWO listeners:
135
+ # :4105 = PUBLIC (MCP + workbench), JWT-gated — published below.
136
+ # :4106 = INTERNAL node runtime (catalog + execute) + builder MCP, UNGATED —
137
+ # published LOOPBACK-ONLY (127.0.0.1). The Docker network and the host
138
+ # machine itself are the trust boundary: nothing off the machine can
139
+ # reach it. This is how a dev's local Claude Code drives the workflow
140
+ # builder (/mcp-builder); never widen it to "4106:4106".
141
+ unoverse:
142
+ image: registry.digitalocean.com/gravity-repo/unoverse:latest
143
+ # For local development, build from source instead:
144
+ # build:
145
+ # context: .
146
+ # dockerfile: apps/unoverse/Dockerfile
147
+ ports:
148
+ - "4105:4105" # PUBLIC port
149
+ - "127.0.0.1:4106:4106" # builder MCP + runtime, LOOPBACK ONLY — local Claude Code connects here; never "4106:4106"
150
+ # LOOPBACK ONLY. The engine surface is unauthenticated; a plain "4101:4101" is
151
+ # internet-reachable on a VM because Docker's iptables rules BYPASS ufw — the
152
+ # harden.yml firewall does not protect published ports. Host tooling (./unoverse key,
153
+ # health checks) still reaches it via 127.0.0.1. Never widen to "4101:4101".
154
+ - "127.0.0.1:4101:4101" # workflow surface (engine in-process)
155
+ environment:
156
+ - NODE_ENV=production
157
+ # Studio is a separate app, launched by the CLI from source. It is not in this image
158
+ # and has no switch here: the Docker runtime serves MCP + API only.
159
+ - UNOVERSE_PORT=4105
160
+ # PUBLIC origin the app's OWN /mcp + /stream live at — baked into each MCP app's
161
+ # widget CSP (openai/widgetCSP.connect_domains). MUST be the api.<domain> host, or
162
+ # the widget (running in ChatGPT's iframe) is CSP-blocked from calling back and renders
163
+ # blank. Derived from DOMAIN like every other HTTPS URL (set DOMAIN only); empty in dev,
164
+ # where the code falls back to localhost:4105.
165
+ - UNOVERSE_PUBLIC_URL=${DOMAIN:+https://api.${DOMAIN:-}}
166
+ - UNOVERSE_RUNTIME_PORT=4106
167
+ # The internal listeners (:4106 runtime, :4101 engine) bind LOOPBACK by default in
168
+ # code. Inside the container they must bind all interfaces (docker-proxy and sibling
169
+ # containers connect to the container IP); the loopback-only port mappings above and
170
+ # the Docker network are the boundary here.
171
+ - UNOVERSE_INTERNAL_BIND=0.0.0.0
172
+ - AUTH_ISSUER=${AUTH_ISSUER:-}
173
+ - AUTH_AUDIENCE=${AUTH_AUDIENCE:-}
174
+ # WHERE THE MARKETPLACE IS. The catalogue this universe can install from, served as
175
+ # static files (catalogue.json plus each item's own definition). No default: a baked
176
+ # URL ties the image to one deployment and hides a missing setting. Empty means no
177
+ # remote catalogue, and the universe offers only what is on its own disk, which is
178
+ # what the monorepo and an air-gapped install both want.
179
+ - UNOVERSE_MARKETPLACE_URL=${UNOVERSE_MARKETPLACE_URL:-}
180
+ - OPENAI_API_KEY=${OPENAI_API_KEY:-}
181
+ # Optional: page-intelligence features (promote-page extraction).
182
+ - HYPERBROWSER_API_KEY=${HYPERBROWSER_API_KEY:-}
183
+ # TEMP test shim: SearchPlaces/SearchAPI env fallback when no credential is stored.
184
+ - SERVER_WS_URL=ws://server:4100
185
+ # In-process loopback: the engine runs IN THIS container and binds :4101.
186
+ - WORKFLOW_SERVICE_URL=http://127.0.0.1:4101
187
+ # Lifecycle bridge: subscribes gravity:client:* and projects WORKFLOW_STATE
188
+ # onto MCP /stream sessions (lifecycleBridge.ts).
189
+ - REDIS_HOST=${REDIS_HOST:-}
190
+ - REDIS_PORT=${REDIS_PORT:-}
191
+ - REDIS_PASSWORD=${REDIS_PASSWORD:-}
192
+ - REDIS_TLS=${REDIS_TLS:-}
193
+ # ── ONE_ENGINE CUTOVER ACTIVE: DATABASE_URL is the capability gate that boots
194
+ # the in-process engine (the retired workflow block above is the rollback).
195
+ - DATABASE_URL=${DATABASE_URL:-}
196
+ # Connection budget (INFRASTRUCTURE.md, Postgres law) — per-size values
197
+ # rendered by the infra Terraform; unset in local dev = code defaults (10).
198
+ - DB_POOL_ENGINE=${DB_POOL_ENGINE:-}
199
+ - DB_POOL_ENGINE_LEGACY=${DB_POOL_ENGINE_LEGACY:-}
200
+ # Encrypts stored credentials at rest. WITHOUT this the engine falls back to a
201
+ # key committed in source (SECURITY.md § Credential encryption at rest) — set it
202
+ # in every deployment: openssl rand -base64 32
203
+ - CREDENTIAL_ENCRYPTION_KEY=${CREDENTIAL_ENCRYPTION_KEY:-}
204
+ - REDIS_NAMESPACE=${REDIS_NAMESPACE:-}
205
+ - UMAP_SERVICE_URL=http://umap:5001
206
+ # Agent nodes POST conversation turns to the memory server (ingestConversationTurn).
207
+ # Without this the code falls back to http://localhost:4104 — nothing inside THIS
208
+ # container — so every ingest silently fails (fire-and-forget) and memory never
209
+ # updates on deployed envs. The memory server is the sibling `memory` container.
210
+ - MEMORY_SERVICE_URL=http://memory:4114
211
+ # Marketplace installs node packages here at runtime (npm) — nodes are NOT baked
212
+ # into the image; only the core workflow nodes ship with the platform (in the
213
+ # workflow image). This volume persists installs across restarts.
214
+ - PLUGINS_DIR=/app/plugins
215
+ # Dev-editable folders are mounted over the image below; NODE_PATH resolves
216
+ # their hoisted deps from the local workspace node_modules. The plugins dir is
217
+ # also on NODE_PATH so locally-built component nodes (apps/unoverse/nodes/*, which
218
+ # live OUTSIDE /app/plugins) can resolve @unoverse-platform/plugin-base — the only
219
+ # copy carrying a built dist. Without this the runtime hits MODULE_NOT_FOUND and
220
+ # the nodes show "Package not installed".
221
+ - NODE_PATH=/app/host_node_modules:/app/plugins/node_modules
222
+ volumes:
223
+ - unoverse_plugins:/app/plugins
224
+ # ── Platform-dev mounts (monorepo only; sync-starter strips these three
225
+ # lines from the starter's copy — a customer universe serves what the DB
226
+ # says). Local edits are picked up on restart; rx/prompts are data, no build.
227
+ - ./node_modules:/app/host_node_modules # Hoisted deps for locally-built nodes
228
+ healthcheck:
229
+ # Ready = internal runtime port up (nodes are loaded into memory BEFORE it binds).
230
+ test:
231
+ ["CMD", "node", "-e", "fetch('http://127.0.0.1:4106/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
232
+ interval: 5s
233
+ timeout: 3s
234
+ retries: 12
235
+ start_period: 10s
236
+ labels:
237
+ - "com.docker.compose.service=unoverse"
238
+ logging: *default-logging
239
+ restart: unless-stopped
240
+
241
+ # RETIRED (2026-07): the standalone mcp-server (external OpenAI-Apps/Claude MCP on
242
+ # :4103) is superseded by the unoverse server's NATIVE MCP — public :4105/mcp and
243
+ # internal :4106/mcp (the app-discovery/workflow-MCP path). Source moved to
244
+ # _legacy/mcp-server; the last gravity-repo/mcp-server image stays in DOCR as the
245
+ # rollback hatch. ROLLBACK: restore apps/mcp-server from _legacy, re-add to the CI
246
+ # matrix, uncomment this block.
247
+ # mcp-server:
248
+ # image: registry.digitalocean.com/gravity-repo/mcp-server:latest
249
+ # ports:
250
+ # - "4103:4103"
251
+ # environment:
252
+ # - NODE_ENV=production
253
+ # - DOMAIN=${DOMAIN:-}
254
+ # - WORKFLOW_SERVICE_URL=http://unoverse:4101
255
+ # - AUTH_ISSUER=${AUTH_ISSUER:-}
256
+ # - AUTH_AUDIENCE=${AUTH_AUDIENCE:-}
257
+ # labels:
258
+ # - "com.docker.compose.service=mcp-server"
259
+ # depends_on:
260
+ # - unoverse
261
+ # logging: *default-logging
262
+ # restart: unless-stopped
263
+
264
+ # Memory Server - Evidence-based user memory system (ambient pub/sub, Redis Streams)
265
+ memory:
266
+ image: registry.digitalocean.com/gravity-repo/memory:${TAG:-latest}
267
+ ports:
268
+ - "4104:4104"
269
+ environment:
270
+ - NODE_ENV=production
271
+ - PORT=4104
272
+ - DATABASE_URL=${DATABASE_URL:-}
273
+ # Connection budget (INFRASTRUCTURE.md) — Terraform-rendered per size.
274
+ - DB_POOL_MEMORY=${DB_POOL_MEMORY:-}
275
+ - REDIS_HOST=${REDIS_HOST:-}
276
+ - REDIS_PORT=${REDIS_PORT:-}
277
+ - REDIS_PASSWORD=${REDIS_PASSWORD:-}
278
+ - REDIS_TLS=${REDIS_TLS:-}
279
+ - REDIS_NAMESPACE=${REDIS_NAMESPACE:-}
280
+ - AUTH_ISSUER=${AUTH_ISSUER:-}
281
+ - AUTH_AUDIENCE=${AUTH_AUDIENCE:-}
282
+ - OPENAI_API_KEY=${OPENAI_API_KEY:-}
283
+ - WORKFLOW_SERVICE_URL=http://unoverse:4101
284
+ labels:
285
+ - "com.docker.compose.service=memory"
286
+ depends_on:
287
+ - unoverse
288
+ logging: *default-logging
289
+ restart: unless-stopped
290
+
291
+ # unoverse-runtime REMOVED 2026-07-28: WIP, excluded from the platform
292
+ # (docs/architecture/INFRASTRUCTURE.md). Returns when the user declares it ready.
293
+
294
+ # ===========================================================================
295
+ # OBSERVABILITY — log viewer (runs by default)
296
+ # ===========================================================================
297
+ # Dozzle: a single ~30 MB container that tails/searches every container's logs
298
+ # in a live web UI. Stores NOTHING (streams from the Docker socket on demand),
299
+ # needs no config, no datasource, no dashboards. Replaces the old
300
+ # Promtail→Loki→Grafana stack. Long-term retention is bounded by the json-file
301
+ # log rotation set on each service (x-logging anchor above).
302
+ #
303
+ # No `profiles:` — logs are core, so dozzle starts with a plain `up -d` and
304
+ # survives `unoverse update` (a profiled service is skipped by up -d and would
305
+ # silently stay down after every update).
306
+ dozzle:
307
+ image: amir20/dozzle:latest
308
+ container_name: gravity-dozzle
309
+ ports:
310
+ - "8080:8080"
311
+ volumes:
312
+ - /var/run/docker.sock:/var/run/docker.sock:ro
313
+ logging: *default-logging
314
+ restart: unless-stopped
315
+
316
+ volumes:
317
+ umap_models:
318
+ unoverse_plugins: # Marketplace-installed node packages (persisted across restarts)
@@ -54,6 +54,6 @@ roles = [
54
54
  # can bring them back. Never commit it; keep a safe copy with your database backups.
55
55
  # To change any value: edit this file and re-render. Never hand-edit the output.
56
56
 
57
- # Marketplace catalogue to install from (docs/architecture/MARKETPLACE.md).
58
- # Leave unset for local items only.
59
- # marketplace_url = "https://marketplace.example.com"
57
+ # Marketplace catalogue. Defaults to the official one — set this only to point somewhere
58
+ # else, or to "" for local items only.
59
+ # marketplace_url = "https://your-own-marketplace.example.com"
@@ -92,15 +92,20 @@ variable "hyperbrowser_api_key" {
92
92
  sensitive = true
93
93
  }
94
94
 
95
- # The catalogue this universe installs from (MARKETPLACE.md §5). NO DEFAULT, deliberately:
96
- # a URL is never hardcoded and never a fallback, and absent config means no remote
97
- # catalogue the universe serves what it has on disk and in its rows, which is the correct
98
- # state for development and for air-gapped estates. It reaches the marketplace at install
99
- # time and at no other time.
95
+ # The catalogue this universe installs from (MARKETPLACE.md §5).
96
+ #
97
+ # DEFAULTS TO THE OFFICIAL MARKETPLACE (decided 2026-08-03). It used to have none, on the
98
+ # rule that a URL is never hardcoded — right for a URL only the operator can know, wrong for
99
+ # this one: the official catalogue is the platform's own address, the same for every
100
+ # universe, and requiring each developer to paste it made "install from the marketplace" a
101
+ # setup step instead of a thing that works.
102
+ #
103
+ # Set it to your own to point elsewhere, or to "" for local items only — which is still the
104
+ # correct state for an air-gapped estate, and still not an error.
100
105
  variable "marketplace_url" {
101
106
  description = "Base URL of the marketplace catalogue. Empty = local items only."
102
107
  type = string
103
- default = ""
108
+ default = "https://unoverse-marketplace-4hlb9.ondigitalocean.app"
104
109
  }
105
110
 
106
111
  # YOUR public key, uploaded as this universe's EC2 key pair. Deploying means ssh-ing from
@@ -51,6 +51,6 @@ openai_api_key = "sk-..." # memory server + OpenAI nodes
51
51
  # can bring them back. Never commit it; keep a safe copy with your database backups.
52
52
  # To change any value: edit this file and re-render. Never hand-edit the output.
53
53
 
54
- # Marketplace catalogue to install from (docs/architecture/MARKETPLACE.md).
55
- # Leave unset for local items only.
56
- # marketplace_url = "https://marketplace.example.com"
54
+ # Marketplace catalogue. Defaults to the official one — set this only to point somewhere
55
+ # else, or to "" for local items only.
56
+ # marketplace_url = "https://your-own-marketplace.example.com"
@@ -126,13 +126,18 @@ variable "hyperbrowser_api_key" {
126
126
  sensitive = true
127
127
  }
128
128
 
129
- # The catalogue this universe installs from (MARKETPLACE.md §5). NO DEFAULT, deliberately:
130
- # a URL is never hardcoded and never a fallback, and absent config means no remote
131
- # catalogue the universe serves what it has on disk and in its rows, which is the correct
132
- # state for development and for air-gapped estates. It reaches the marketplace at install
133
- # time and at no other time.
129
+ # The catalogue this universe installs from (MARKETPLACE.md §5).
130
+ #
131
+ # DEFAULTS TO THE OFFICIAL MARKETPLACE (decided 2026-08-03). It used to have none, on the
132
+ # rule that a URL is never hardcoded — right for a URL only the operator can know, wrong for
133
+ # this one: the official catalogue is the platform's own address, the same for every
134
+ # universe, and requiring each developer to paste it made "install from the marketplace" a
135
+ # setup step instead of a thing that works.
136
+ #
137
+ # Set it to your own to point elsewhere, or to "" for local items only — which is still the
138
+ # correct state for an air-gapped estate, and still not an error.
134
139
  variable "marketplace_url" {
135
140
  description = "Base URL of the marketplace catalogue. Empty = local items only."
136
141
  type = string
137
- default = ""
142
+ default = "https://unoverse-marketplace-4hlb9.ondigitalocean.app"
138
143
  }
@@ -77,6 +77,22 @@ case "${1:-}" in
77
77
  # The ground definitions first: they are code, and they update like code.
78
78
  # NO `local` HERE: a case branch in the dispatch is not a function body, and bash
79
79
  # errors "local: can only be used in a function" straight to the developer's screen.
80
+ # THE COMPOSE FILE UPDATES LIKE THE GROUND DOES. A universe's docker-compose.yml was
81
+ # written once at creation and never again, so every platform change to it — a new
82
+ # service, a new environment variable — reached the monorepo and the starter and
83
+ # stopped there. UNOVERSE_MARKETPLACE_URL was rendered into .env by the ground and
84
+ # shipped by the deploy, and the container still never saw it, because the compose on
85
+ # that universe had no line to pass it through.
86
+ #
87
+ # Their .env is untouched: compose reads values from it and holds none.
88
+ _vcompose="$GRAVITY_LIB/../docker-compose.yml"
89
+ if [ -f "$_vcompose" ] && [ -f "$ROOT/docker-compose.yml" ]; then
90
+ if ! cmp -s "$_vcompose" "$ROOT/docker-compose.yml"; then
91
+ cp "$_vcompose" "$ROOT/docker-compose.yml"
92
+ ok "Refreshed docker-compose.yml ${DIM}(your .env is untouched)${NC}"
93
+ fi
94
+ fi
95
+
80
96
  _vinfra="$GRAVITY_LIB/../infra"
81
97
  if [ -d "$_vinfra" ]; then
82
98
  for _g in digitalocean aws; do
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unoverse",
3
- "version": "0.1.110",
3
+ "version": "0.1.112",
4
4
  "description": "The Unoverse front door — create a Studio project, a universe, or a client app, and launch Studio.",
5
5
  "license": "SEE LICENSE IN README.md",
6
6
  "type": "module",