@volter/world-runtime 2.0.27 → 2.0.29

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.
@@ -12,6 +12,7 @@ export declare function sealTwinCredential(worldRoot: string, vendor: string, pa
12
12
  export declare function sealedCredentialInfo(worldRoot: string, vendor: string): {
13
13
  placedAt: string;
14
14
  fingerprint: string;
15
+ sealedBy: 'vault' | 'key';
15
16
  } | null;
16
17
  /** The signing secret sealed beside the credential (`{ headers, signingSecret }`), for ingest; null when none. */
17
18
  export declare function twinSigningSecret(worldRoot: string, vendor: string): Promise<string | null>;
package/dist/src/root.js CHANGED
@@ -11,7 +11,7 @@ import { packEntry } from "./catalog.js";
11
11
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
12
12
  import { homedir } from 'node:os';
13
13
  import { dirname, join, relative, resolve } from 'node:path';
14
- import { authStrategyFor, getActiveWorldStore, getPack, sealingKey, buildRemoteExecute, clearRoot, openSealedCredential, readRoot, registerStateSystem, sealCredential, stateDirName, stateSystemFor, validateRemoteOrigin, writeRoot, } from '@volter/world-core';
14
+ import { authStrategyFor, currentSealer, openSealedAt, getActiveWorldStore, getPack, buildRemoteExecute, clearRoot, readRoot, registerStateSystem, stateDirName, stateSystemFor, validateRemoteOrigin, writeRoot, } from '@volter/world-core';
15
15
  import { loadWorldConfig, writeWorldConfig } from "./configs.js";
16
16
  import { changesetReadiness, collectObservations, foldObservations, loadChecks, openRootCredential, performEntries, rootCustody, protocolStanding } from '@volter/world-core';
17
17
  import { findWorldChangeset, listWorldChangesets } from "./changeset.js";
@@ -31,7 +31,7 @@ export function credentialPath(worldRoot, vendor) {
31
31
  return join(resolve(worldRoot), stateDirName(), 'credentials', `${vendor}.json`);
32
32
  }
33
33
  export async function sealTwinCredential(worldRoot, vendor, payload, at = new Date().toISOString()) {
34
- const sealed = await sealCredential(sealingKey(), payload, at, vendor);
34
+ const sealed = await currentSealer().seal(payload, at, vendor);
35
35
  getActiveWorldStore().write(credentialPath(worldRoot, vendor), `${JSON.stringify(sealed, null, 2)}\n`, { secret: true });
36
36
  return { placedAt: sealed.placedAt, fingerprint: sealed.fingerprint };
37
37
  }
@@ -40,14 +40,14 @@ export function sealedCredentialInfo(worldRoot, vendor) {
40
40
  if (text === null)
41
41
  return null;
42
42
  const sealed = JSON.parse(text);
43
- return { placedAt: sealed.placedAt, fingerprint: sealed.fingerprint };
43
+ // what wraps it: a vault's transit key (v: 2) or a key the host holds (v: 1), so an operator sees what still needs one
44
+ return { placedAt: sealed.placedAt, fingerprint: sealed.fingerprint, sealedBy: sealed.v === 2 ? 'vault' : 'key' };
44
45
  }
45
46
  /** The signing secret sealed beside the credential (`{ headers, signingSecret }`), for ingest; null when none. */
46
47
  export async function twinSigningSecret(worldRoot, vendor) {
47
- const text = getActiveWorldStore().read(credentialPath(worldRoot, vendor));
48
- if (text === null)
48
+ const payload = await openSealedAt(credentialPath(worldRoot, vendor), vendor);
49
+ if (payload === null)
49
50
  return null;
50
- const payload = await openSealedCredential(sealingKey(), JSON.parse(text), vendor);
51
51
  return typeof payload.signingSecret === 'string' && payload.signingSecret.length >= 8 ? payload.signingSecret : null;
52
52
  }
53
53
  // ── where a root's credential comes from (company decision 0033) ────────────────────────────
@@ -26,7 +26,7 @@ import { getActiveWorldStore, withAncestryLock, captureHistory, historyAtInstant
26
26
  // to `.volter/token` and `.volter/token.read` (0600).
27
27
  // One writer per world by construction: the doors run in this process, serialized per twin.
28
28
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
29
- import { blobDigest, getActiveBlobStore, loadCheck, mirrorShellUnder, openSealedCredential, readTwinRequestJournal, sealingKey, serveHttp, TWIN_PREFIX_HEADER, validateRemoteOrigin } from '@volter/world-core';
29
+ import { blobDigest, openSealedAt, getActiveBlobStore, loadCheck, mirrorShellUnder, readTwinRequestJournal, serveHttp, TWIN_PREFIX_HEADER, validateRemoteOrigin } from '@volter/world-core';
30
30
  import { APP_READ_ENDPOINT_ENV } from "./init.js";
31
31
  import { grantOf, presentedSecrets, sameSecret, spentPasses, verifyPass } from '@volter/world-access';
32
32
  import { createHash } from 'node:crypto';
@@ -912,10 +912,9 @@ export class WorldDoors {
912
912
  * token removed and the sealed credential's headers replacing any of the same name. The vendor's
913
913
  * answer (status, headers, body) is streamed back as it arrives. */
914
914
  async forward(request, url, rest, name, origin) {
915
- const sealed = getActiveWorldStore().read(credentialPath(this.worldRoot, name));
916
- if (sealed === null)
915
+ const credential = await openSealedAt(credentialPath(this.worldRoot, name), name);
916
+ if (credential === null)
917
917
  return Response.json({ error: `the ${name} link has no credential sealed` }, { status: 409 });
918
- const credential = await openSealedCredential(sealingKey(), JSON.parse(sealed), name);
919
918
  const base = validateRemoteOrigin(origin);
920
919
  const target = new URL(`${base.origin}/${rest}${url.search}`);
921
920
  if (target.origin !== base.origin)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world-runtime",
3
- "version": "2.0.27",
3
+ "version": "2.0.29",
4
4
  "description": "World configs for twins: boot named local runtimes, allocate ports, generate world.env/instance.json, and run apps against fake-key twin worlds.",
5
5
  "keywords": [
6
6
  "twin",
@@ -67,14 +67,14 @@
67
67
  "node": ">=22.3"
68
68
  },
69
69
  "peerDependencies": {
70
- "@volter/world-core": "2.0.15",
70
+ "@volter/world-core": "2.0.17",
71
71
  "@volter/world-console": "2.0.10"
72
72
  },
73
73
  "dependencies": {
74
74
  "@electric-sql/pglite": "0.5.8",
75
75
  "@electric-sql/pglite-pgvector": "0.0.9",
76
76
  "@volter/world-access": "2.0.2",
77
- "@volter/world-core": "2.0.15",
77
+ "@volter/world-core": "2.0.17",
78
78
  "pg-gateway": "0.3.0-beta.4",
79
79
  "smol-toml": "^1.8.0"
80
80
  },
@@ -84,6 +84,6 @@
84
84
  }
85
85
  },
86
86
  "optionalDependencies": {
87
- "@volter/twin-mongodb": "0.1.15"
87
+ "@volter/twin-mongodb": "0.1.17"
88
88
  }
89
89
  }
package/src/root.ts CHANGED
@@ -12,7 +12,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
12
12
  import { homedir } from 'node:os';
13
13
  import { basename, dirname, join, relative, resolve } from 'node:path';
14
14
  import {
15
- NO_SECRETS_CHECK, authStrategyFor, getActiveWorldStore, getPack, sealingKey, buildRemoteExecute, clearRoot, observeAppends, openSealedCredential, readRoot, registerStateSystem, sealCredential, stateDirName, stateSystemFor, type Check, type CredentialPayload, type PerformAction, type PushReport, type RemoteExecute, type RootConfig, type SealedCredential, type TwinAction, validateRemoteOrigin, writeRoot,
15
+ NO_SECRETS_CHECK, authStrategyFor, currentSealer, openSealedAt, getActiveWorldStore, getPack, buildRemoteExecute, clearRoot, observeAppends, readRoot, registerStateSystem, stateDirName, stateSystemFor, type Check, type CredentialPayload, type PerformAction, type PushReport, type RemoteExecute, type RootConfig, type SealedCredential, type TwinAction, validateRemoteOrigin, writeRoot,
16
16
  } from '@volter/world-core';
17
17
  import { loadWorldConfig, writeWorldConfig } from './configs.ts';
18
18
  import { changesetReadiness, collectObservations, type Observation, foldObservations, loadChecks, openRootCredential, performEntries, rootCustody, protocolStanding, userKek, type DeployReport, type ObserveReport } from '@volter/world-core';
@@ -38,21 +38,21 @@ export function credentialPath(worldRoot: string, vendor: string): string {
38
38
  return join(resolve(worldRoot), stateDirName(), 'credentials', `${vendor}.json`);
39
39
  }
40
40
  export async function sealTwinCredential(worldRoot: string, vendor: string, payload: CredentialPayload, at: string = new Date().toISOString()): Promise<{ placedAt: string; fingerprint: string }> {
41
- const sealed = await sealCredential(sealingKey(), payload, at, vendor);
41
+ const sealed = await currentSealer().seal(payload, at, vendor);
42
42
  getActiveWorldStore().write(credentialPath(worldRoot, vendor), `${JSON.stringify(sealed, null, 2)}\n`, { secret: true });
43
43
  return { placedAt: sealed.placedAt, fingerprint: sealed.fingerprint };
44
44
  }
45
- export function sealedCredentialInfo(worldRoot: string, vendor: string): { placedAt: string; fingerprint: string } | null {
45
+ export function sealedCredentialInfo(worldRoot: string, vendor: string): { placedAt: string; fingerprint: string; sealedBy: 'vault' | 'key' } | null {
46
46
  const text = getActiveWorldStore().read(credentialPath(worldRoot, vendor));
47
47
  if (text === null) return null;
48
48
  const sealed = JSON.parse(text) as SealedCredential;
49
- return { placedAt: sealed.placedAt, fingerprint: sealed.fingerprint };
49
+ // what wraps it: a vault's transit key (v: 2) or a key the host holds (v: 1), so an operator sees what still needs one
50
+ return { placedAt: sealed.placedAt, fingerprint: sealed.fingerprint, sealedBy: sealed.v === 2 ? 'vault' : 'key' };
50
51
  }
51
52
  /** The signing secret sealed beside the credential (`{ headers, signingSecret }`), for ingest; null when none. */
52
53
  export async function twinSigningSecret(worldRoot: string, vendor: string): Promise<string | null> {
53
- const text = getActiveWorldStore().read(credentialPath(worldRoot, vendor));
54
- if (text === null) return null;
55
- const payload = await openSealedCredential(sealingKey(), JSON.parse(text) as SealedCredential, vendor);
54
+ const payload = await openSealedAt(credentialPath(worldRoot, vendor), vendor);
55
+ if (payload === null) return null;
56
56
  return typeof payload.signingSecret === 'string' && payload.signingSecret.length >= 8 ? payload.signingSecret : null;
57
57
  }
58
58
 
@@ -26,7 +26,7 @@ import { getActiveWorldStore, withAncestryLock, captureHistory, historyAtInstant
26
26
  // to `.volter/token` and `.volter/token.read` (0600).
27
27
  // One writer per world by construction: the doors run in this process, serialized per twin.
28
28
  import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync , rmSync} from 'node:fs';
29
- import { blobDigest, getActiveBlobStore, loadCheck, mirrorShellUnder, openSealedCredential, readTwinRequestJournal, sealingKey, serveHttp, TWIN_PREFIX_HEADER, validateRemoteOrigin, type SealedCredential, type TwinStreamConnection, type TwinStreamSink } from '@volter/world-core';
29
+ import { blobDigest, openSealedAt, getActiveBlobStore, loadCheck, mirrorShellUnder, readTwinRequestJournal, serveHttp, TWIN_PREFIX_HEADER, validateRemoteOrigin, type SealedCredential, type TwinStreamConnection, type TwinStreamSink } from '@volter/world-core';
30
30
  import { APP_READ_ENDPOINT_ENV } from './init.ts';
31
31
  import { grantOf, presentedSecrets, sameSecret, spentPasses, verifyPass, type TrustedIssuer, type WorldCredentials } from '@volter/world-access';
32
32
  import { createHash } from 'node:crypto';
@@ -817,9 +817,8 @@ export class WorldDoors {
817
817
  * token removed and the sealed credential's headers replacing any of the same name. The vendor's
818
818
  * answer (status, headers, body) is streamed back as it arrives. */
819
819
  private async forward(request: Request, url: URL, rest: string, name: string, origin: string): Promise<Response> {
820
- const sealed = getActiveWorldStore().read(credentialPath(this.worldRoot, name));
821
- if (sealed === null) return Response.json({ error: `the ${name} link has no credential sealed` }, { status: 409 });
822
- const credential = await openSealedCredential(sealingKey(), JSON.parse(sealed) as SealedCredential, name);
820
+ const credential = await openSealedAt(credentialPath(this.worldRoot, name), name);
821
+ if (credential === null) return Response.json({ error: `the ${name} link has no credential sealed` }, { status: 409 });
823
822
  const base = validateRemoteOrigin(origin);
824
823
  const target = new URL(`${base.origin}/${rest}${url.search}`);
825
824
  if (target.origin !== base.origin) return Response.json({ error: 'the path left the link origin' }, { status: 400 });