@volter/world 2.0.32 → 2.0.33
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/world.js +16 -3
- package/package.json +3 -3
- package/src/world.ts +14 -3
package/dist/src/world.js
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
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, rootCredentialInput, withoutVaultSignIn, 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, bindLegacyCredentials, 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";
|
|
12
12
|
import { currentBranch, findWorldRoot, mainBranch, requireWorldRoot, setCurrentBranch, worldConfigRelative, worldEnvPath, worldSeedPath } from "./locate.js";
|
|
13
|
-
import { parentEntries, rebaseBranch } from '@volter/world-core';
|
|
13
|
+
import { destinationOf, parentEntries, rebaseBranch } from '@volter/world-core';
|
|
14
14
|
/** One change as `log` shows it: the write, and the receipt the vendor answered with once pushed. */
|
|
15
15
|
/** A twin's branch log as the world reads it: the twin's name, the state service it records under, its control root. */
|
|
16
16
|
/** `30d`, `12h`, `5m`, `90s` in ms. */
|
|
@@ -501,12 +501,25 @@ export class World {
|
|
|
501
501
|
}
|
|
502
502
|
}
|
|
503
503
|
/** Seal the vendor's credential beside the world (a bare token, or a JSON payload). Never readable back. */
|
|
504
|
-
sealTwinCredential(vendor, input) {
|
|
504
|
+
sealTwinCredential(vendor, input) {
|
|
505
|
+
// sealed for the one destination it serves, the twin's root: with none set there is nowhere it may go
|
|
506
|
+
const url = loadWorldConfig(this.configRef(), this.root).config.services.find((s) => s.id === vendor)?.root?.url;
|
|
507
|
+
if (!url)
|
|
508
|
+
return Promise.reject(new Error(`the ${vendor} twin has no root: \`volter twin ${vendor} root <url>\` sets where its credential goes, then seal it`));
|
|
509
|
+
return sealTwinCredential(this.root, vendor, credentialPayloadFrom(input, vendor), undefined, destinationOf(url));
|
|
510
|
+
}
|
|
505
511
|
/** A root's credential when none is piped in: the signed-in vault, else the repo's `.env` (decision 0033). */
|
|
506
512
|
rootCredentialInput(vendor) { return rootCredentialInput(this.root, vendor); }
|
|
507
513
|
/** Refresh one twin from its root now. */
|
|
508
514
|
async refreshTwin(vendor, opts = {}) {
|
|
509
515
|
const { controlRoot, root } = this.rootOf(vendor);
|
|
516
|
+
// a credential sealed before bindings is bound to this root first: the person at this machine set both
|
|
517
|
+
// credentials sealed before bindings are bound first, each to its twin's root in world.json (the person at this
|
|
518
|
+
// machine set both); the inventory is the World's own, so it takes every twin's root, not just this one's
|
|
519
|
+
const roots = () => Object.fromEntries(loadWorldConfig(this.configRef(), this.root).config.services.filter((s) => s.id && s.root?.url).map((s) => [s.id, s.root.url]));
|
|
520
|
+
const legacy = await bindLegacyCredentials(this.root, roots);
|
|
521
|
+
if (!legacy.ready)
|
|
522
|
+
throw new Error('the credentials beside this World could not be inventoried');
|
|
510
523
|
return refreshTwin({ worldRoot: this.root, vendor, controlRoot, root, ...(opts.force ? { force: true } : {}) });
|
|
511
524
|
}
|
|
512
525
|
rootOf(vendor) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/world",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.33",
|
|
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.
|
|
34
|
-
"@volter/world-runtime": "2.0.
|
|
33
|
+
"@volter/world-core": "2.0.18",
|
|
34
|
+
"@volter/world-runtime": "2.0.31",
|
|
35
35
|
"zod": "^4.6.5"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
package/src/world.ts
CHANGED
|
@@ -8,14 +8,14 @@ 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, rootCredentialInput, withoutVaultSignIn,
|
|
11
|
+
bindLegacyCredentials, 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';
|
|
15
15
|
import { dirname, join, resolve } from 'node:path';
|
|
16
16
|
import { requireToken, storeToken } from './credentials.ts';
|
|
17
17
|
import { currentBranch, findWorldRoot, mainBranch, requireWorldRoot, setCurrentBranch, worldConfigRelative, worldEnvPath, worldSeedPath } from './locate.ts';
|
|
18
|
-
import { parentEntries, rebaseBranch, type Receipt, type RootConfig } from '@volter/world-core';
|
|
18
|
+
import { destinationOf, parentEntries, rebaseBranch, type Receipt, type RootConfig } from '@volter/world-core';
|
|
19
19
|
|
|
20
20
|
export type WorldRef = { name?: string; root?: string };
|
|
21
21
|
export type WorldMode = 'local' | 'share' | 'sealed';
|
|
@@ -460,12 +460,23 @@ export class World {
|
|
|
460
460
|
if (inst?.running) { materializeRoots(loadWorldConfig(this.configRef(), this.root).config, inst.dirs.data, this.root); }
|
|
461
461
|
}
|
|
462
462
|
/** Seal the vendor's credential beside the world (a bare token, or a JSON payload). Never readable back. */
|
|
463
|
-
sealTwinCredential(vendor: string, input: string): Promise<{ placedAt: string; fingerprint: string }> {
|
|
463
|
+
sealTwinCredential(vendor: string, input: string): Promise<{ placedAt: string; fingerprint: string }> {
|
|
464
|
+
// sealed for the one destination it serves, the twin's root: with none set there is nowhere it may go
|
|
465
|
+
const url = (loadWorldConfig(this.configRef(), this.root).config.services as Array<{ id?: string; root?: { url?: string } }>).find((s) => s.id === vendor)?.root?.url;
|
|
466
|
+
if (!url) return Promise.reject(new Error(`the ${vendor} twin has no root: \`volter twin ${vendor} root <url>\` sets where its credential goes, then seal it`));
|
|
467
|
+
return sealTwinCredential(this.root, vendor, credentialPayloadFrom(input, vendor), undefined, destinationOf(url));
|
|
468
|
+
}
|
|
464
469
|
/** A root's credential when none is piped in: the signed-in vault, else the repo's `.env` (decision 0033). */
|
|
465
470
|
rootCredentialInput(vendor: string): ReturnType<typeof rootCredentialInput> { return rootCredentialInput(this.root, vendor); }
|
|
466
471
|
/** Refresh one twin from its root now. */
|
|
467
472
|
async refreshTwin(vendor: string, opts: { force?: boolean } = {}): Promise<{ refreshed: boolean; reason?: string; report?: { observed: number; appended: number; unchanged: number; removed: number } }> {
|
|
468
473
|
const { controlRoot, root } = this.rootOf(vendor);
|
|
474
|
+
// a credential sealed before bindings is bound to this root first: the person at this machine set both
|
|
475
|
+
// credentials sealed before bindings are bound first, each to its twin's root in world.json (the person at this
|
|
476
|
+
// machine set both); the inventory is the World's own, so it takes every twin's root, not just this one's
|
|
477
|
+
const roots = () => Object.fromEntries((loadWorldConfig(this.configRef(), this.root).config.services as Array<{ id?: string; root?: { url?: string } }>).filter((s) => s.id && s.root?.url).map((s) => [s.id!, s.root!.url!]));
|
|
478
|
+
const legacy = await bindLegacyCredentials(this.root, roots);
|
|
479
|
+
if (!legacy.ready) throw new Error('the credentials beside this World could not be inventoried');
|
|
469
480
|
return refreshTwin({ worldRoot: this.root, vendor, controlRoot, root, ...(opts.force ? { force: true } : {}) });
|
|
470
481
|
}
|
|
471
482
|
private rootOf(vendor: string): { controlRoot: string; root: MaterializedRoot } {
|