@volter/world-runtime 2.0.0

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 (164) hide show
  1. package/LICENSE +202 -0
  2. package/dist/known-external-services.json +1108 -0
  3. package/dist/src/ancestry.d.ts +2 -0
  4. package/dist/src/ancestry.js +42 -0
  5. package/dist/src/app-url.d.ts +47 -0
  6. package/dist/src/app-url.js +239 -0
  7. package/dist/src/attach.d.ts +48 -0
  8. package/dist/src/attach.js +87 -0
  9. package/dist/src/branch.d.ts +20 -0
  10. package/dist/src/branch.js +65 -0
  11. package/dist/src/browser-proxy-cli.d.ts +2 -0
  12. package/dist/src/browser-proxy-cli.js +41 -0
  13. package/dist/src/ca-trust.d.ts +5 -0
  14. package/dist/src/ca-trust.js +64 -0
  15. package/dist/src/catalog.d.ts +31 -0
  16. package/dist/src/catalog.js +148 -0
  17. package/dist/src/changeset.d.ts +142 -0
  18. package/dist/src/changeset.js +570 -0
  19. package/dist/src/cli.d.ts +2 -0
  20. package/dist/src/cli.js +1262 -0
  21. package/dist/src/command-lifetime.d.ts +15 -0
  22. package/dist/src/command-lifetime.js +98 -0
  23. package/dist/src/configs.d.ts +18 -0
  24. package/dist/src/configs.js +119 -0
  25. package/dist/src/console-apart.d.ts +38 -0
  26. package/dist/src/console-apart.js +107 -0
  27. package/dist/src/consumers.d.ts +46 -0
  28. package/dist/src/consumers.js +200 -0
  29. package/dist/src/covers.d.ts +183 -0
  30. package/dist/src/covers.js +800 -0
  31. package/dist/src/fixture-env.d.ts +42 -0
  32. package/dist/src/fixture-env.js +221 -0
  33. package/dist/src/host-cli.d.ts +2 -0
  34. package/dist/src/host-cli.js +92 -0
  35. package/dist/src/host-fault-fixture.d.ts +32 -0
  36. package/dist/src/host-fault-fixture.js +100 -0
  37. package/dist/src/host-worker.d.ts +1 -0
  38. package/dist/src/host-worker.js +23 -0
  39. package/dist/src/host.d.ts +38 -0
  40. package/dist/src/host.js +135 -0
  41. package/dist/src/index.d.ts +48 -0
  42. package/dist/src/index.js +35 -0
  43. package/dist/src/infra-cli.d.ts +2 -0
  44. package/dist/src/infra-cli.js +136 -0
  45. package/dist/src/init.d.ts +227 -0
  46. package/dist/src/init.js +1117 -0
  47. package/dist/src/inject-map.d.ts +34 -0
  48. package/dist/src/inject-map.js +56 -0
  49. package/dist/src/lifecycle-record.d.ts +47 -0
  50. package/dist/src/lifecycle-record.js +196 -0
  51. package/dist/src/origin.d.ts +31 -0
  52. package/dist/src/origin.js +139 -0
  53. package/dist/src/pack-facts.d.ts +75 -0
  54. package/dist/src/pack-facts.js +98 -0
  55. package/dist/src/pglite-backing.d.ts +21 -0
  56. package/dist/src/pglite-backing.js +158 -0
  57. package/dist/src/pglite-host.mjs +147 -0
  58. package/dist/src/placeholder.d.ts +20 -0
  59. package/dist/src/placeholder.js +100 -0
  60. package/dist/src/prerequisites.d.ts +21 -0
  61. package/dist/src/prerequisites.js +49 -0
  62. package/dist/src/process-groups.d.ts +4 -0
  63. package/dist/src/process-groups.js +49 -0
  64. package/dist/src/project-inspect.d.ts +109 -0
  65. package/dist/src/project-inspect.js +827 -0
  66. package/dist/src/proxy-daemon.d.ts +2 -0
  67. package/dist/src/proxy-daemon.js +18 -0
  68. package/dist/src/redirect-proxy.d.ts +105 -0
  69. package/dist/src/redirect-proxy.js +665 -0
  70. package/dist/src/reflect.d.ts +74 -0
  71. package/dist/src/reflect.js +392 -0
  72. package/dist/src/resources.d.ts +26 -0
  73. package/dist/src/resources.js +22 -0
  74. package/dist/src/root.d.ts +114 -0
  75. package/dist/src/root.js +312 -0
  76. package/dist/src/run-task-worker.d.ts +1 -0
  77. package/dist/src/run-task-worker.js +38 -0
  78. package/dist/src/run-task.d.ts +18 -0
  79. package/dist/src/run-task.js +48 -0
  80. package/dist/src/runtime-test-support.d.ts +59 -0
  81. package/dist/src/runtime-test-support.js +205 -0
  82. package/dist/src/runtime.d.ts +256 -0
  83. package/dist/src/runtime.js +3502 -0
  84. package/dist/src/schema.d.ts +449 -0
  85. package/dist/src/schema.js +605 -0
  86. package/dist/src/serve.d.ts +30 -0
  87. package/dist/src/serve.js +82 -0
  88. package/dist/src/served-world.d.ts +194 -0
  89. package/dist/src/served-world.js +986 -0
  90. package/dist/src/service-exit.d.ts +46 -0
  91. package/dist/src/service-exit.js +195 -0
  92. package/dist/src/service-recorder.d.ts +1 -0
  93. package/dist/src/service-recorder.js +121 -0
  94. package/dist/src/sibling.d.ts +1 -0
  95. package/dist/src/sibling.js +9 -0
  96. package/dist/src/signals.d.ts +1 -0
  97. package/dist/src/signals.js +11 -0
  98. package/dist/src/storage-capacity.d.ts +8 -0
  99. package/dist/src/storage-capacity.js +61 -0
  100. package/dist/src/tail.d.ts +30 -0
  101. package/dist/src/tail.js +160 -0
  102. package/dist/src/tcp-port.d.ts +2 -0
  103. package/dist/src/tcp-port.js +36 -0
  104. package/dist/src/up-task-worker.d.ts +1 -0
  105. package/dist/src/up-task-worker.js +61 -0
  106. package/dist/src/up-task.d.ts +17 -0
  107. package/dist/src/up-task.js +49 -0
  108. package/dist/src/websocket-relay.d.ts +3 -0
  109. package/dist/src/websocket-relay.js +40 -0
  110. package/known-external-services.json +1108 -0
  111. package/package.json +83 -0
  112. package/src/ancestry.ts +36 -0
  113. package/src/app-url.ts +253 -0
  114. package/src/attach.ts +117 -0
  115. package/src/branch.ts +63 -0
  116. package/src/browser-proxy-cli.ts +44 -0
  117. package/src/ca-trust.ts +57 -0
  118. package/src/catalog.ts +156 -0
  119. package/src/changeset.ts +627 -0
  120. package/src/cli.ts +1111 -0
  121. package/src/command-lifetime.ts +79 -0
  122. package/src/configs.ts +110 -0
  123. package/src/console-apart.ts +90 -0
  124. package/src/consumers.ts +185 -0
  125. package/src/covers.ts +934 -0
  126. package/src/fixture-env.ts +230 -0
  127. package/src/host-cli.ts +90 -0
  128. package/src/host-worker.ts +23 -0
  129. package/src/host.ts +169 -0
  130. package/src/index.ts +171 -0
  131. package/src/infra-cli.ts +133 -0
  132. package/src/init.ts +1316 -0
  133. package/src/inject-map.ts +72 -0
  134. package/src/lifecycle-record.ts +168 -0
  135. package/src/origin.ts +134 -0
  136. package/src/pack-facts.ts +128 -0
  137. package/src/pglite-backing.ts +141 -0
  138. package/src/pglite-host.mjs +147 -0
  139. package/src/placeholder.ts +89 -0
  140. package/src/prerequisites.ts +66 -0
  141. package/src/process-groups.ts +33 -0
  142. package/src/project-inspect.ts +770 -0
  143. package/src/proxy-daemon.ts +21 -0
  144. package/src/redirect-proxy.ts +684 -0
  145. package/src/reflect.ts +440 -0
  146. package/src/resources.ts +22 -0
  147. package/src/root.ts +290 -0
  148. package/src/run-task-worker.ts +27 -0
  149. package/src/run-task.ts +44 -0
  150. package/src/runtime-test-support.ts +208 -0
  151. package/src/runtime.ts +3357 -0
  152. package/src/schema.ts +922 -0
  153. package/src/serve.ts +102 -0
  154. package/src/served-world.ts +812 -0
  155. package/src/service-exit.ts +175 -0
  156. package/src/service-recorder.ts +89 -0
  157. package/src/sibling.ts +10 -0
  158. package/src/signals.ts +10 -0
  159. package/src/storage-capacity.ts +60 -0
  160. package/src/tail.ts +205 -0
  161. package/src/tcp-port.ts +35 -0
  162. package/src/up-task-worker.ts +40 -0
  163. package/src/up-task.ts +45 -0
  164. package/src/websocket-relay.ts +32 -0
@@ -0,0 +1,449 @@
1
+ import { type WorldNetwork } from '@volter/world-core/network-policy';
2
+ export type WorldServiceType = 'twin' | 'process' | 'external';
3
+ export type WorldMode = 'local' | 'share' | 'sealed';
4
+ /**
5
+ * Process model for the world's twins — a DIAL, not a binary (see src/host.ts):
6
+ * - 'process' (default): one OS process per service — the existing spawn path. Strongest
7
+ * service-to-service process separation (not a network or Machine boundary),
8
+ * isolation; the oracle, and the only choice for share/sealed/hosted worlds
9
+ * (enforced by `upWorld` — see runtime.ts, not just documented here; TWIN-67).
10
+ * - 'colocated': every service declaring `colocate` runs in ONE `volter-world-host` child
11
+ * sharing a single event loop + heap (host 'shared' mode). Lightest.
12
+ * - 'worker' : same single host child, but one Worker thread per twin — own event loop +
13
+ * heap, independently isolated (a crashed twin stays dead — never respawned),
14
+ * still one OS process to the orchestrator.
15
+ * Services without `colocate` (and all 'external' services) always use the spawn path.
16
+ */
17
+ export type WorldIsolation = 'process' | 'colocated' | 'worker';
18
+ export declare const WORLD_SCHEMA_VERSION: 2;
19
+ export declare const WORLD_USAGES: readonly ["application", "dependencies", "build", "deployment"];
20
+ export type WorldUsage = typeof WORLD_USAGES[number];
21
+ export type WorldSelectionSelector = {
22
+ usage?: WorldUsage;
23
+ vendor?: string;
24
+ };
25
+ export type WorldSelection = {
26
+ include: WorldSelectionSelector[];
27
+ exclude: WorldSelectionSelector[];
28
+ };
29
+ /** The format-2 document is normalized to WorldConfig before runtime code sees it. */
30
+ export type WorldManifestV2 = {
31
+ schemaVersion: 2;
32
+ metadata: {
33
+ id: string;
34
+ description?: string;
35
+ };
36
+ discovery?: {
37
+ selection?: WorldSelection;
38
+ };
39
+ services: unknown[];
40
+ runtime?: {
41
+ isolation?: WorldIsolation;
42
+ environment?: {
43
+ values?: Record<string, string>;
44
+ strip?: string[];
45
+ };
46
+ network?: WorldNetwork;
47
+ };
48
+ serving?: {
49
+ mode?: 'app' | 'bare';
50
+ name?: string;
51
+ share?: WorldShareConfig;
52
+ };
53
+ remotes?: Record<string, string>;
54
+ scenario?: {
55
+ actors?: Record<string, unknown>;
56
+ fixtures?: Record<string, unknown>;
57
+ };
58
+ provenance?: {
59
+ catalog?: {
60
+ sha: string;
61
+ protocol?: string;
62
+ };
63
+ };
64
+ };
65
+ /** The env value `init` writes for a name whose fake must be minted per instance (a service-account JSON with a real throwaway key). */
66
+ export declare const MINT_ENV = "$mint";
67
+ export type WorldShareProvider = 'cloudflare-quick' | 'command';
68
+ /**
69
+ * EXTERNAL (self-managed) service type.
70
+ *
71
+ * Most services in a world are owned by us: we spawn `command`, assign a PORT, and inject a
72
+ * `*_URL` (types 'twin' and 'process'). An EXTERNAL service is the opposite: its lifecycle is
73
+ * DELEGATED to an external tool that runs the REAL software (e.g. Supabase's `supabase start`,
74
+ * LocalStack, MinIO, Mailpit). We do NOT assign it a port — the external tool manages its own
75
+ * ports — and its connection URL + keys are DISCOVERED from the tool's own output, then injected
76
+ * into the world env exactly like a twin's `injectEnv`.
77
+ *
78
+ * The runtime is deliberately VENDOR-AGNOSTIC: it never branches on a tool's identity. Everything
79
+ * the runtime needs (how to start, how to probe readiness, how to read connection info, how to
80
+ * stop) is declared in the config below. Supabase is just an EXAMPLE config (see
81
+ * `configs/supabase-world.json`, which mixes a Supabase external service with stripe/github twins);
82
+ * there is zero Supabase-specific code in `runtime.ts`.
83
+ *
84
+ * Lifecycle on world `up`:
85
+ * 1. run `up` (start the external stack),
86
+ * 2. wait for `readyWhen` (Docker-backed externals take seconds to boot),
87
+ * 3. run `status` (or reuse `up` output) to obtain connection info,
88
+ * 4. apply `discover` mappings → inject env vars into the world env (and world.env/instance.json).
89
+ * On world teardown (`down`): run `down` for each external service.
90
+ *
91
+ * Robustness contract: if the external tool is missing on PATH, or `up`/`status` fail, or
92
+ * readiness times out, world `up` fails LOUDLY with the captured output — never a fake success.
93
+ */
94
+ /** Source of the text a `discover` mapping reads from: the `status` output (default) or `up` output. */
95
+ export type WorldExternalDiscoverSource = 'status' | 'up';
96
+ /**
97
+ * One declarative env-var extraction. Exactly one of `jsonPath` or `pattern` must be set.
98
+ * - `jsonPath`: dotted path into the JSON the source command printed (e.g. `API_URL`, `db.url`,
99
+ * `services.0.endpoint`). Numeric segments index into arrays.
100
+ * - `pattern`: a regex applied to the raw source text; capture group `value` (or group 1) is used.
101
+ * The resolved value is injected as the env var named by `as`.
102
+ */
103
+ export type WorldExternalDiscover = {
104
+ as: string;
105
+ source?: WorldExternalDiscoverSource;
106
+ jsonPath?: string;
107
+ pattern?: string;
108
+ };
109
+ /**
110
+ * Optional readiness probe, polled after `up` until it passes or `timeoutMs` elapses. Exactly one of:
111
+ * - `command`/`args`: a command that must exit 0,
112
+ * - `httpUrl`: an HTTP(S) URL that must return a 2xx/3xx response,
113
+ * - `stdoutMatch`: a regex that must appear in the `up` command's captured stdout/stderr log.
114
+ */
115
+ export type WorldExternalReadyWhen = {
116
+ command?: string;
117
+ args?: string[];
118
+ httpUrl?: string;
119
+ stdoutMatch?: string;
120
+ timeoutMs?: number;
121
+ intervalMs?: number;
122
+ };
123
+ export type WorldExternalServiceConfig = {
124
+ up: string[];
125
+ status?: string[];
126
+ down: string[];
127
+ discover?: WorldExternalDiscover[];
128
+ readyWhen?: WorldExternalReadyWhen;
129
+ };
130
+ export type WorldShareServiceConfig = {
131
+ id: string;
132
+ verifyPath?: string | false;
133
+ };
134
+ export type WorldShareConfig = {
135
+ provider?: WorldShareProvider;
136
+ /** Custom tunnel command (provider 'command'). `{url}` in args is replaced with the
137
+ * service's local URL. When set, provider defaults to 'command'. */
138
+ command?: string;
139
+ args?: string[];
140
+ /** Lifecycle, independent of provider type. Cloudflare Quick Tunnels are always ephemeral;
141
+ * custom providers state the same fact explicitly when teardown retires the URL. */
142
+ ephemeral?: boolean;
143
+ services: WorldShareServiceConfig[];
144
+ };
145
+ /** Deprecated metadata from runtime v2. Not reserved or enforced by local runtime v3. */
146
+ export type WorldResourceRequirements = {
147
+ memoryMiB: number;
148
+ writableStorageMiB: number;
149
+ };
150
+ export type WorldServiceConfig = {
151
+ /**
152
+ * A free-text NOTE about this service, ignored by the runtime — JSON has no comments, and a
153
+ * generated config needs somewhere to say WHY it is shaped the way it is. `volter-world init`
154
+ * writes the wiring rationale here (which `*_TWIN_URL` the injector actually reads, or why a
155
+ * vendor has no endpoint env at all), so an operator reading the emitted file is not left to
156
+ * reverse-engineer the decision. Hand-written configs may use it freely.
157
+ */
158
+ '//'?: string;
159
+ id: string;
160
+ type?: WorldServiceType;
161
+ /**
162
+ * The twin PACKAGE this service boots from (`@volter/twin-<vendor>`), resolved from the world
163
+ * root at boot by node's own `node_modules` walk (docs/concepts/worlds.md#the-config-and-the-running-world).
164
+ * With `package` set, `command` and the entry are derived (`bun <pkg>/src/cli.ts serve`), `args`
165
+ * are appended after `serve`, and a `colocate` without a `module` boots `<pkg>/src/index.ts`.
166
+ * A config written inside this checkout names checkout-relative paths instead.
167
+ */
168
+ package?: string;
169
+ /** Required for 'twin'/'process' services without `package`. Omitted for 'external' (the tool's `up`/`down` hold the commands). */
170
+ command?: string;
171
+ args?: string[];
172
+ /** Optional working directory for this process. Relative paths resolve from the world root. */
173
+ cwd?: string;
174
+ port?: number | 'auto';
175
+ /**
176
+ * Required whenever `port` is a literal number (schema-enforced, TWIN-66): stable configs are
177
+ * meant to be instance-agnostic (see docs/concepts/worlds.md's config/instance split), so a numeric port is the
178
+ * declared EXCEPTION, not the norm — it must record WHY the port can't be `'auto'`-allocated
179
+ * (e.g. a consumer needs a pre-known issuer/callback URL baked in elsewhere). Ignored/forbidden
180
+ * when `port` is `'auto'` or unset.
181
+ */
182
+ portReason?: string;
183
+ env?: Record<string, string>;
184
+ /**
185
+ * Marks this service as world infrastructure rather than an app/vendor process.
186
+ *
187
+ * Control-plane services still receive the world's declared/injected service env, but they do not
188
+ * inherit app-side egress machinery (`NODE_OPTIONS` injector preload or ambient HTTP(S) proxy env).
189
+ * Use this for helper proxies, seeders, local asset servers, or orchestration daemons that must talk
190
+ * to loopback services directly while presenting a disguised world to the app/user.
191
+ */
192
+ controlPlane?: boolean;
193
+ injectEnv?: string;
194
+ /**
195
+ * Additional env vars exported into the generated world env after this service starts.
196
+ * Templates are resolved against the owned loopback service:
197
+ * - `${url}` / `${httpUrl}` → http://127.0.0.1:<port>
198
+ * - `${host}` → 127.0.0.1
199
+ * - `${port}` → the allocated port
200
+ * This is the process-service equivalent of external.discover for services whose client-facing
201
+ * endpoint is not the default http URL, e.g. a real local LiveKit server needing ws://.
202
+ */
203
+ injectEnvTemplates?: Record<string, string>;
204
+ /** THE ROOT (contract "The model"): the vendor's real account behind this twin on a shared world —
205
+ * its API (or the one resource the account is), the deploy policy, how it is refreshed. Key-free;
206
+ * the credential is sealed under `.volter/credentials/`. Written by `volter twin <vendor> root`. */
207
+ root?: {
208
+ url: string;
209
+ deploy: 'auto' | 'gated' | 'hold';
210
+ refresh?: {
211
+ every?: string;
212
+ webhook?: boolean;
213
+ };
214
+ scope?: string;
215
+ };
216
+ rootArg?: string | false;
217
+ portArg?: string | false;
218
+ /**
219
+ * Optional per-CLI redirect: env vars exported into the world env so the vendor's REAL CLI
220
+ * (`aws`, `gh`, `sentry-cli`, …) talks to THIS service instead of the real vendor. The literal
221
+ * `${url}` is substituted with the service's resolved URL — e.g. `{ "AWS_ENDPOINT_URL": "${url}" }`.
222
+ * Honored by `volter-world env/run/activate` (it flows into the world env like `injectEnv`). The
223
+ * pure-env path for CLIs that accept an http endpoint; CLIs needing https use the proxy (Phase 2).
224
+ * See docs/guides/route-a-cli-through-the-world.md.
225
+ */
226
+ cliRedirect?: Record<string, string>;
227
+ /**
228
+ * Readiness probe for a 'process'/'twin' service. The default (or `'tcp'`) waits only until the
229
+ * port accepts TCP connections — but a process can bind its port BEFORE it is actually serving
230
+ * (Vite, an HTTP app warming up a DB pool). Pass a probe object to make `up` wait until the
231
+ * service truly serves, so `up` returning means "ready" (no post-up re-polling needed):
232
+ * - `{ httpUrl }` — poll until 2xx/3xx. `${url}`/`${host}`/`${port}` resolve to the allocated port.
233
+ * - `{ command, args }` — poll until the command exits 0 (runs with the service env, incl. `PORT`).
234
+ * - `{ stdoutMatch }` — poll until a regex matches the service's stdout/stderr log.
235
+ * 'external' services use `external.readyWhen` instead.
236
+ */
237
+ ready?: 'tcp' | WorldExternalReadyWhen;
238
+ /**
239
+ * Extra Node preloads for a 'process'/'twin' service, appended as `--require <module>` to the
240
+ * world's NODE_OPTIONS (which already loads `@volter/world-core/inject`). Use this to add an app-local
241
+ * preload (e.g. an in-process sandbox) WITHOUT losing the injector. Setting `service.env.NODE_OPTIONS`
242
+ * directly REPLACES the world default (dropping the injector) — only do that if you truly mean to.
243
+ */
244
+ preload?: string[];
245
+ /** Required when `type === 'external'`: the self-managed lifecycle (up/status/down/discover/readyWhen). */
246
+ external?: WorldExternalServiceConfig;
247
+ /**
248
+ * Names this twin's in-process server factory so it can run CO-LOCATED inside the single
249
+ * `volter-world-host` child when the world's isolation is 'colocated'/'worker'. `module` is
250
+ * anything `import()` resolves — a package name (`@volter/twin-stripe`) or a file path
251
+ * (relative paths resolve from the world root); `export` names a
252
+ * `({port,root,readOnly}) => {port,stop}` factory (every pack ships one, e.g.
253
+ * `createStripeTwinServer`). Ignored under 'process' isolation (the default), where
254
+ * `command` is spawned as usual — declare BOTH to let one config serve every dial setting.
255
+ */
256
+ colocate?: {
257
+ module?: string;
258
+ export: string; /** the handlers file a scenario-carrying twin loads (R2a) */
259
+ scenarioPath?: string;
260
+ };
261
+ /** R17 — the external lockfile: pins the twin package's own version (its package.json). `up`
262
+ * refuses a mounted package that does not satisfy it, naming both; `init` emits it from the
263
+ * catalog the world was born against. Exact version or `^major.minor` range. */
264
+ version?: string;
265
+ };
266
+ export type WorldConfig = {
267
+ id: string;
268
+ /** Real external origins; omitted preserves legacy routing, [] explicitly closes egress. */
269
+ network?: WorldNetwork;
270
+ /** Internal normalized source format and saved discovery selection. */
271
+ manifestVersion?: 1 | 2;
272
+ selection?: WorldSelection;
273
+ description?: string;
274
+ /** A world with no app in front of it (`init --bare <org>/<world>`): a shared world for a team, or a
275
+ * world standing in for a vendor. `name` is how it is served: `/<org>/<world>/…`. */
276
+ bare?: {
277
+ name: string;
278
+ };
279
+ /** The worlds this one pushes to and fetches from, by name (`volter remote add`); `origin` is the
280
+ * default. A URL a served world printed, or a path to a world's directory. Tokens are never here. */
281
+ remotes?: Record<string, string>;
282
+ /** Peak capacity for this World. Conservative defaults are used when omitted for compatibility;
283
+ * resource-intensive Worlds should always declare both values explicitly. */
284
+ resources?: WorldResourceRequirements;
285
+ /** Default process model for this world's twins ('process' when omitted). `upWorld`'s
286
+ * `isolation` option overrides it per boot. */
287
+ isolation?: WorldIsolation;
288
+ /** The world's env. A value of `$mint` (MINT_ENV) is minted at boot — a structurally valid
289
+ * throwaway credential for that name (fixture-env) — and lives only in the live env file, so a
290
+ * committed config never holds key material. */
291
+ env?: Record<string, string>;
292
+ /** Variables of the process that runs the world which never enter it — a name, a prefix ending in `*`, or `*` for all inherited variables
293
+ * (`HERMES_*`). The world seals what leaves over the wire; this seals what comes in through the environment:
294
+ * whatever steered the outer process (an agent's worker pinning its board and run) must not steer what runs
295
+ * inside, whose state is the world's own. Applied to every service the world starts and to `env`/`attach`. */
296
+ stripEnv?: string[];
297
+ services: WorldServiceConfig[];
298
+ share?: WorldShareConfig;
299
+ actors?: Record<string, unknown>;
300
+ fixtures?: Record<string, unknown>;
301
+ /** The birth stamp (R18), written by `init`: the catalog sha the world was born against and
302
+ * the platform protocol major it was born under. `up` reads the major back and refuses a
303
+ * world this platform can no longer read by construction (two majors back, or newer). */
304
+ catalog?: {
305
+ sha: string;
306
+ protocol?: string;
307
+ };
308
+ };
309
+ export type WorldServiceInstance = {
310
+ id: string;
311
+ type: WorldServiceType;
312
+ command: string[];
313
+ /** R17 — what the host actually mounted for a colocated twin: the package version read from
314
+ * the module's own package.json, and the protocol standing (R16) it declared. */
315
+ resolvedVersion?: string;
316
+ protocol?: {
317
+ declared?: string;
318
+ major: number;
319
+ standing: string;
320
+ };
321
+ /** Absent for 'external' services — we do not assign them a port. */
322
+ port?: number;
323
+ /** Absent for 'external' services — their URL is discovered into env vars, not assigned by us. */
324
+ url?: string;
325
+ /** 0 for 'external' services — they have no process we own (the external tool manages it). */
326
+ pid: number;
327
+ log: string;
328
+ env: Record<string, string>;
329
+ /**
330
+ * Set only for 'external' services. Records the `down` command so teardown can stop the
331
+ * self-managed stack, plus the cwd it was started from (the marker that the stack was brought up).
332
+ */
333
+ external?: {
334
+ down: string[];
335
+ cwd: string;
336
+ /** Env discovered during `up` (the injected vars), passed to the `down` command so teardown can
337
+ * reference connection info it needs (e.g. a stop command that takes the discovered URL). */
338
+ discoveredEnv?: Record<string, string>;
339
+ };
340
+ publicUrl?: string;
341
+ publicUrlEphemeral?: boolean;
342
+ publicReady?: boolean;
343
+ publicVerification?: {
344
+ path: string;
345
+ checkedAt: string;
346
+ hostname: string;
347
+ resolvedIp?: string;
348
+ status?: number;
349
+ body?: string;
350
+ };
351
+ tunnel?: {
352
+ provider: 'cloudflare-quick' | 'command';
353
+ pid: number;
354
+ log: string;
355
+ command: string[];
356
+ startedAt: string;
357
+ };
358
+ /**
359
+ * Set for a 'worker'-isolated co-located twin whose host-managed Worker thread crashed and
360
+ * was given up on (never respawned — still discoverable: the port answers nothing, but the
361
+ * dead twin is no longer silent). Not written directly by the runtime process: the co-located
362
+ * host CHILD records it in a sidecar file (`host-gaveup.json`, same instance dir) since it
363
+ * cannot safely rewrite instance.json out from under the parent; `readWorldInstance` merges
364
+ * the sidecar in here so every reader sees it as if it were in instance.json all along.
365
+ */
366
+ workerGaveUp?: {
367
+ /** ISO timestamp of the give-up. */
368
+ at: string;
369
+ /** Exits observed for this twin under the no-respawn contract (always 1 — field kept for
370
+ * record compatibility with the sidecar/schema shape). */
371
+ exits: number;
372
+ detail: string;
373
+ };
374
+ };
375
+ /** Durable outcome of the most recent foreground consumer launched by `volter-world run`.
376
+ * Deliberately excludes argv and environment values: both can contain credentials. */
377
+ export type WorldRunOutcome = {
378
+ state: 'completed';
379
+ runnerPid: number;
380
+ startedAt: string;
381
+ finishedAt: string;
382
+ exitCode: number;
383
+ log: string;
384
+ signal?: NodeJS.Signals;
385
+ error?: string;
386
+ };
387
+ export type WorldRunRecord = WorldRunOutcome | {
388
+ state: 'running';
389
+ runnerPid: number;
390
+ consumerPid?: number;
391
+ startedAt: string;
392
+ log: string;
393
+ } | {
394
+ state: 'abrupt';
395
+ runnerPid: number;
396
+ consumerPid?: number;
397
+ startedAt: string;
398
+ observedAt: string;
399
+ log: string;
400
+ error: string;
401
+ };
402
+ export type WorldInstance = {
403
+ name: string;
404
+ /** Snapshot of the selection in force when this instance booted. */
405
+ selection?: WorldSelection;
406
+ config: string;
407
+ configPath: string;
408
+ root: string;
409
+ createdAt: string;
410
+ mode: WorldMode;
411
+ dirs: {
412
+ instance: string;
413
+ logs: string;
414
+ data: string;
415
+ };
416
+ services: Record<string, WorldServiceInstance>;
417
+ env: Record<string, string>;
418
+ envFile: string;
419
+ pidsFile: string;
420
+ actors?: Record<string, unknown>;
421
+ fixtures?: Record<string, unknown>;
422
+ /** Legacy runtime ownership; finish teardown with that installation before migration. */
423
+ resources?: WorldResourceRequirements & {
424
+ log: string;
425
+ holderPid: number;
426
+ owner?: string;
427
+ };
428
+ lifecycle?: {
429
+ log: string;
430
+ owner?: string;
431
+ holderPid?: number;
432
+ };
433
+ lastRun?: WorldRunRecord;
434
+ /** The ORIGIN this world clones from and fetches (docs/concepts/the-model.md): a hosted twin's
435
+ * namespace — its canonical history. Absent = the placeholder is the only origin. */
436
+ origin?: {
437
+ url: string;
438
+ namespace: string;
439
+ clonedAt?: string;
440
+ fetchedAt?: string;
441
+ };
442
+ };
443
+ export declare const DEFAULT_WORLD_SELECTION: WorldSelection;
444
+ export declare const LEGACY_WORLD_SELECTION: WorldSelection;
445
+ export declare function assertWorldSelection(value: unknown, path: string): asserts value is WorldSelection;
446
+ export declare function assertWorldConfig(value: unknown, path: string): WorldConfig;
447
+ export declare function worldSelectionIncludes(selection: WorldSelection, vendor: string, usage: WorldUsage): boolean;
448
+ /** Serialize normalized intent as the committed format-2 manifest. */
449
+ export declare function worldConfigDocument(config: WorldConfig, selection?: WorldSelection): WorldManifestV2 & Record<string, unknown>;