@volter/world 2.0.28 → 2.0.30

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/dist/src/cli.js CHANGED
@@ -15,6 +15,7 @@ import { forgetPlatform, forgetToken, platformOrigin, storePlatform, storeToken,
15
15
  import { parseOriginUrl, World } from "./world.js";
16
16
  import { waitForServeShutdown } from "./serve-shutdown.js";
17
17
  import { startUpdateCheck } from "./update-notice.js";
18
+ import { withoutVaultSignIn } from '@volter/world-runtime';
18
19
  /** Open a URL in the person's browser; a machine without one only loses the convenience. */
19
20
  function openInBrowser(url) {
20
21
  // an http(s) URL only, and on Windows through the URL handler rather than cmd.exe, which would read `"`, `&` or `%VAR%`
@@ -608,9 +609,19 @@ async function twinCommand(args) {
608
609
  world.setTwinRoot(vendor, { url, deploy, ...(value(rest, '--scope') ? { scope: value(rest, '--scope') } : {}), ...(Object.keys(refresh).length ? { refresh } : {}) });
609
610
  }
610
611
  else if (verb === 'credential') {
611
- const input = stdinText();
612
- if (input.trim() === '')
613
- throw new Error(`volter twin ${vendor} credential: read the credential from stdin (printf '<token>' | volter twin ${vendor} credential)`);
612
+ // what is piped in, else the signed-in vault, else the repo's .env (company decision 0033: no vault required)
613
+ let input = process.stdin.isTTY ? '' : stdinText();
614
+ if (input.trim() === '') {
615
+ if (!world.twin(vendor))
616
+ throw new Error(`volter twin ${vendor} credential: this World has no twin "${vendor}"`);
617
+ const found = await world.rootCredentialInput(vendor);
618
+ for (const note of found.notes)
619
+ process.stderr.write(`${vendor} ${note}\n`);
620
+ if (found.input === null)
621
+ throw new Error(`volter twin ${vendor} credential: no credential found. Pipe one (printf '<token>' | volter twin ${vendor} credential), sign in to a vault holding kv/vendors/${vendor}, or put it in the repo's .env`);
622
+ out(`${vendor} credential from ${found.from}`);
623
+ input = found.input;
624
+ }
614
625
  await world.sealTwinCredential(vendor, input);
615
626
  }
616
627
  else if (verb === 'refresh') {
@@ -961,7 +972,8 @@ async function installDetectedTwins(app, install) {
961
972
  throw new Error(`install the twins first: ${command}
962
973
  then run volter world init again (or volter world init --install does both)`);
963
974
  // one command line built from the checked names above: nothing of anyone's input reaches the shell
964
- const ran = spawnSync(command, { cwd: app, stdio: 'inherit', shell: true, windowsHide: true });
975
+ // a dependency's install script is not Volter's: it never sees the person's vault sign-in
976
+ const ran = spawnSync(command, { cwd: app, stdio: 'inherit', shell: true, windowsHide: true, env: withoutVaultSignIn(process.env) });
965
977
  if (ran.status !== 0)
966
978
  throw new Error(`${command} failed (exit ${ran.status ?? 'none'})`);
967
979
  }
@@ -1,5 +1,5 @@
1
1
  import { rebaseChangeset, worldBootMarker, type Changeset, type LedgerDelta, type TwinAction, type WorldMarker, type ApplyReceipt, applyTwinWrite, type TwinResource } from '@volter/world-core';
2
- import { approveWorldChangeset, createWorldChangeset, downWorld, fetchFromOrigin, pushWorldChangeset, rebaseWorldChangeset, replayWorldChangeset, resetWorld, seedWorld, statusWorldChangeset, verifyWorldChangeset, type ServedWorld, type ViewConsole, type WorldView, type DeployTwinOutcome, type ChangesetLocation, type InitOptions, type InitResult, type WorldInstance } from '@volter/world-runtime';
2
+ import { approveWorldChangeset, createWorldChangeset, downWorld, fetchFromOrigin, pushWorldChangeset, rebaseWorldChangeset, replayWorldChangeset, resetWorld, seedWorld, statusWorldChangeset, verifyWorldChangeset, type ServedWorld, type ViewConsole, type WorldView, rootCredentialInput, type DeployTwinOutcome, type ChangesetLocation, type InitOptions, type InitResult, type WorldInstance } from '@volter/world-runtime';
3
3
  import { rebaseBranch, type Receipt, type RootConfig } from '@volter/world-core';
4
4
  export type WorldRef = {
5
5
  name?: string;
@@ -296,6 +296,8 @@ export declare class World {
296
296
  placedAt: string;
297
297
  fingerprint: string;
298
298
  }>;
299
+ /** A root's credential when none is piped in: the signed-in vault, else the repo's `.env` (decision 0033). */
300
+ rootCredentialInput(vendor: string): ReturnType<typeof rootCredentialInput>;
299
301
  /** Refresh one twin from its root now. */
300
302
  refreshTwin(vendor: string, opts?: {
301
303
  force?: boolean;
package/dist/src/world.js CHANGED
@@ -5,7 +5,7 @@
5
5
  import { rebaseChangeset, worldBootMarker, listActions, isTwinBookkeeping, pushablePendingActions, pendingActions, applyTwinWrite, twinResources } from '@volter/world-core';
6
6
  import { spawnSync } from 'node:child_process';
7
7
  import clockForm from '@volter/world-core/world-clock';
8
- import { activateScript, approveWorldChangeset, branchWorld, clockFile, checkoutWorld, createWorldChangeset, diffWorld, downWorld, fetchFromOrigin, findWorldChangeset, initWorld, listWorldChangesets, listWorldMarks, listWorlds, markWorld, pushWorldChangeset, rebaseWorldChangeset, replayWorldChangeset, resetWorld, runWithWorldEnv, seedWorld, shellWorld, statusWorld, statusWorldChangeset, upWorld, verifyWorldChangeset, worldLedgers, worldOrigin, deployWorld, loadWorldConfig, writeWorldConfig, readServeRecord, refreshTwin, serveWorld, serveWorldView, findInstalledPackage, rootForControlRoot, sealTwinCredential, sealedCredentialInfo, setTwinRoot, credentialPayloadFrom, materializeRoots } from '@volter/world-runtime';
8
+ import { activateScript, approveWorldChangeset, branchWorld, clockFile, checkoutWorld, createWorldChangeset, diffWorld, downWorld, fetchFromOrigin, findWorldChangeset, initWorld, listWorldChangesets, listWorldMarks, listWorlds, markWorld, pushWorldChangeset, rebaseWorldChangeset, replayWorldChangeset, resetWorld, runWithWorldEnv, seedWorld, shellWorld, statusWorld, statusWorldChangeset, upWorld, verifyWorldChangeset, worldLedgers, worldOrigin, deployWorld, loadWorldConfig, writeWorldConfig, readServeRecord, refreshTwin, serveWorld, serveWorldView, findInstalledPackage, rootForControlRoot, sealTwinCredential, sealedCredentialInfo, setTwinRoot, credentialPayloadFrom, rootCredentialInput, withoutVaultSignIn, materializeRoots } from '@volter/world-runtime';
9
9
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
10
10
  import { dirname, join, resolve } from 'node:path';
11
11
  import { requireToken, storeToken } from "./credentials.js";
@@ -94,7 +94,7 @@ export class World {
94
94
  if (opts.install !== false && !twins.every((t) => findInstalledPackage(dir, `@volter/twin-${t}`))) {
95
95
  // the runtime's own installer: bun under Bun, npm under Node — never assumed
96
96
  const cmd = typeof Bun !== 'undefined' ? ['bun', 'add', '-d'] : ['npm', 'install', '--save-dev'];
97
- const r = spawnSync(cmd[0], [...cmd.slice(1), ...twins.map((t) => `@volter/twin-${t}`)], { windowsHide: true, cwd: dir, stdio: 'inherit' });
97
+ const r = spawnSync(cmd[0], [...cmd.slice(1), ...twins.map((t) => `@volter/twin-${t}`)], { windowsHide: true, cwd: dir, stdio: 'inherit', env: withoutVaultSignIn(process.env) });
98
98
  if (r.status !== 0)
99
99
  throw new Error(`installing the twins failed (${cmd.join(' ')} exited ${r.status})`);
100
100
  }
@@ -502,6 +502,8 @@ export class World {
502
502
  }
503
503
  /** Seal the vendor's credential beside the world (a bare token, or a JSON payload). Never readable back. */
504
504
  sealTwinCredential(vendor, input) { return sealTwinCredential(this.root, vendor, credentialPayloadFrom(input, vendor)); }
505
+ /** A root's credential when none is piped in: the signed-in vault, else the repo's `.env` (decision 0033). */
506
+ rootCredentialInput(vendor) { return rootCredentialInput(this.root, vendor); }
505
507
  /** Refresh one twin from its root now. */
506
508
  async refreshTwin(vendor, opts = {}) {
507
509
  const { controlRoot, root } = this.rootOf(vendor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world",
3
- "version": "2.0.28",
3
+ "version": "2.0.30",
4
4
  "description": "Run your app against a world of twins. `World` and `Repo` — one method per verb: init, up, run, log, diff, reset, branch, checkout, clone, fetch, changeset, push — and the `volter` command, one client of them.",
5
5
  "keywords": [
6
6
  "volter",
@@ -30,8 +30,8 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@modelcontextprotocol/sdk": "^1.30.1",
33
- "@volter/world-core": "2.0.15",
34
- "@volter/world-runtime": "2.0.26",
33
+ "@volter/world-core": "2.0.16",
34
+ "@volter/world-runtime": "2.0.28",
35
35
  "zod": "^4.6.5"
36
36
  },
37
37
  "peerDependencies": {
package/src/cli.ts CHANGED
@@ -17,6 +17,7 @@ import { parseOriginUrl, World } from './world.ts';
17
17
  import { waitForServeShutdown } from './serve-shutdown.ts';
18
18
  import { startUpdateCheck } from './update-notice.ts';
19
19
  import type { ViewConsole } from '@volter/world-runtime';
20
+ import { withoutVaultSignIn } from '@volter/world-runtime';
20
21
 
21
22
  /** Open a URL in the person's browser; a machine without one only loses the convenience. */
22
23
  function openInBrowser(url: string): void {
@@ -440,8 +441,16 @@ async function twinCommand(args: string[]): Promise<void> {
440
441
  const refresh = { ...(value(rest, '--refresh') ? { every: value(rest, '--refresh')! } : {}), ...(value(rest, '--at-most') ? { atMost: value(rest, '--at-most')! } : {}) };
441
442
  world.setTwinRoot(vendor, { url, deploy, ...(value(rest, '--scope') ? { scope: value(rest, '--scope')! } : {}), ...(Object.keys(refresh).length ? { refresh } : {}) });
442
443
  } else if (verb === 'credential') {
443
- const input = stdinText();
444
- if (input.trim() === '') throw new Error(`volter twin ${vendor} credential: read the credential from stdin (printf '<token>' | volter twin ${vendor} credential)`);
444
+ // what is piped in, else the signed-in vault, else the repo's .env (company decision 0033: no vault required)
445
+ let input = process.stdin.isTTY ? '' : stdinText();
446
+ if (input.trim() === '') {
447
+ if (!world.twin(vendor)) throw new Error(`volter twin ${vendor} credential: this World has no twin "${vendor}"`);
448
+ const found = await world.rootCredentialInput(vendor);
449
+ for (const note of found.notes) process.stderr.write(`${vendor} ${note}\n`);
450
+ if (found.input === null) throw new Error(`volter twin ${vendor} credential: no credential found. Pipe one (printf '<token>' | volter twin ${vendor} credential), sign in to a vault holding kv/vendors/${vendor}, or put it in the repo's .env`);
451
+ out(`${vendor} credential from ${found.from}`);
452
+ input = found.input;
453
+ }
445
454
  await world.sealTwinCredential(vendor, input);
446
455
  } else if (verb === 'refresh') {
447
456
  const r = await world.refreshTwin(vendor, { force: flag(rest, '--force') });
@@ -703,7 +712,8 @@ async function installDetectedTwins(app: string, install: boolean): Promise<void
703
712
  if (!yes) throw new Error(`install the twins first: ${command}
704
713
  then run volter world init again (or volter world init --install does both)`);
705
714
  // one command line built from the checked names above: nothing of anyone's input reaches the shell
706
- const ran = spawnSync(command, { cwd: app, stdio: 'inherit', shell: true, windowsHide: true });
715
+ // a dependency's install script is not Volter's: it never sees the person's vault sign-in
716
+ const ran = spawnSync(command, { cwd: app, stdio: 'inherit', shell: true, windowsHide: true, env: withoutVaultSignIn(process.env) });
707
717
  if (ran.status !== 0) throw new Error(`${command} failed (exit ${ran.status ?? 'none'})`);
708
718
  }
709
719
 
package/src/world.ts CHANGED
@@ -8,7 +8,7 @@ import clockForm from '@volter/world-core/world-clock';
8
8
  import {
9
9
  activateScript, approveWorldChangeset, branchWorld, clockFile, checkoutWorld, createWorldChangeset, diffWorld, downWorld, fetchFromOrigin, findWorldChangeset, initWorld, listWorldChangesets, listWorldMarks, listWorlds, markWorld, pushWorldChangeset, rebaseWorldChangeset, replayWorldChangeset, resetWorld, runWithWorldEnv, seedWorld, shellWorld,
10
10
  statusWorld, statusWorldChangeset, upWorld, verifyWorldChangeset, worldLedgers, worldOrigin,
11
- deployWorld, loadWorldConfig, writeWorldConfig, readServeRecord, refreshTwin, serveWorld, serveWorldView, findInstalledPackage, type ServedWorld, type ViewConsole, type WorldView, rootForControlRoot, sealTwinCredential, sealedCredentialInfo, setTwinRoot, credentialPayloadFrom,
11
+ deployWorld, loadWorldConfig, writeWorldConfig, readServeRecord, refreshTwin, serveWorld, serveWorldView, findInstalledPackage, type ServedWorld, type ViewConsole, type WorldView, rootForControlRoot, sealTwinCredential, sealedCredentialInfo, setTwinRoot, credentialPayloadFrom, rootCredentialInput, withoutVaultSignIn,
12
12
  type DeployTwinOutcome, type MaterializedRoot,
13
13
  type ChangesetLocation, type InitOptions, type InitResult, type WorldInstance, materializeRoots } from '@volter/world-runtime';
14
14
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
@@ -108,7 +108,7 @@ export class World {
108
108
  if (opts.install !== false && !twins.every((t) => findInstalledPackage(dir, `@volter/twin-${t}`))) {
109
109
  // the runtime's own installer: bun under Bun, npm under Node — never assumed
110
110
  const cmd = typeof Bun !== 'undefined' ? ['bun', 'add', '-d'] : ['npm', 'install', '--save-dev'];
111
- const r = spawnSync(cmd[0]!, [...cmd.slice(1), ...twins.map((t) => `@volter/twin-${t}`)], { windowsHide: true, cwd: dir, stdio: 'inherit' });
111
+ const r = spawnSync(cmd[0]!, [...cmd.slice(1), ...twins.map((t) => `@volter/twin-${t}`)], { windowsHide: true, cwd: dir, stdio: 'inherit', env: withoutVaultSignIn(process.env) });
112
112
  if (r.status !== 0) throw new Error(`installing the twins failed (${cmd.join(' ')} exited ${r.status})`);
113
113
  }
114
114
  const name = served.split('/')[1]!;
@@ -461,6 +461,8 @@ export class World {
461
461
  }
462
462
  /** Seal the vendor's credential beside the world (a bare token, or a JSON payload). Never readable back. */
463
463
  sealTwinCredential(vendor: string, input: string): Promise<{ placedAt: string; fingerprint: string }> { return sealTwinCredential(this.root, vendor, credentialPayloadFrom(input, vendor)); }
464
+ /** A root's credential when none is piped in: the signed-in vault, else the repo's `.env` (decision 0033). */
465
+ rootCredentialInput(vendor: string): ReturnType<typeof rootCredentialInput> { return rootCredentialInput(this.root, vendor); }
464
466
  /** Refresh one twin from its root now. */
465
467
  async refreshTwin(vendor: string, opts: { force?: boolean } = {}): Promise<{ refreshed: boolean; reason?: string; report?: { observed: number; appended: number; unchanged: number; removed: number } }> {
466
468
  const { controlRoot, root } = this.rootOf(vendor);