@volter/world-core 2.0.4 → 2.0.5
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/head.js +18 -7
- package/package.json +1 -1
- package/src/head.ts +17 -6
package/dist/src/head.js
CHANGED
|
@@ -206,17 +206,28 @@ export async function performEntries(opts) {
|
|
|
206
206
|
queues.set(key, run.catch(() => undefined));
|
|
207
207
|
return run;
|
|
208
208
|
}
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
/** The root a perform runs against: the sealed one, or — when the caller brings its own executor (a library holding
|
|
210
|
+
* the person's token in its own process) — the twin's root.json with no credential sealed at all. */
|
|
211
|
+
function performRoot(service, root, callerExecute) {
|
|
211
212
|
const head = headOf(service, root);
|
|
212
|
-
if (head.kind
|
|
213
|
+
if (head.kind === 'real')
|
|
214
|
+
return { sealed: head.root, vendor: vendorOf(head.root) };
|
|
215
|
+
const unsealed = callerExecute ? readRoot(service, root) : null;
|
|
216
|
+
if (!unsealed)
|
|
213
217
|
throw new Error(`the ${service} twin has no root — nothing to perform against`);
|
|
214
|
-
|
|
218
|
+
return { sealed: null, vendor: service };
|
|
219
|
+
}
|
|
220
|
+
async function performNow(opts) {
|
|
221
|
+
const { service, root } = opts;
|
|
222
|
+
const bound = performRoot(service, root, opts.execute !== undefined);
|
|
223
|
+
const vendor = bound.vendor;
|
|
215
224
|
const adapters = opts.adapters ?? stateSystemFor(vendor) ?? stateSystemFor(service);
|
|
216
225
|
if (!adapters?.perform)
|
|
217
226
|
throw new Error(`the ${vendor} twin has no perform adapter — a protocol 2 pack names one in its descriptor and registers itself (registerPack)`);
|
|
218
|
-
|
|
219
|
-
const
|
|
227
|
+
// the caller's executor, or the one built over the sealed credential; an unsealed root has no other
|
|
228
|
+
const execute = opts.execute ?? buildRemoteExecute(validateRemoteOrigin(bound.sealed.url, { allowInsecureLoopback: true }), await openRootCredential(bound.sealed, vendor), authStrategyFor(vendor), getPack(vendor)?.hosts, { custody: rootCustody(bound.sealed, vendor) });
|
|
229
|
+
// an unsealed root's World is where its state resolves (the root given, PROJECT_ROOT, or the working directory)
|
|
230
|
+
const checks = opts.checks ?? (await loadChecks(bound.sealed ? worldRootOf(bound.sealed) : worldPaths(service, root).root));
|
|
220
231
|
const deployable = deployableEntries(service, root);
|
|
221
232
|
const entries = opts.actionIds === undefined ? deployable : opts.actionIds.map((id) => deployable.find((a) => a.id === id)).filter((a) => a !== undefined);
|
|
222
233
|
const report = { pushed: 0, deployed: [], skipped: [], replayed: [] };
|
|
@@ -244,7 +255,7 @@ async function performNow(opts) {
|
|
|
244
255
|
// a declared reference to an adopted id is resolved before the pack sees the entry: the vendor is
|
|
245
256
|
// asked about #7, never the local #3 (docs/contributing/architecture.md#alias-aware-lookup-at-the-request-boundary)
|
|
246
257
|
const fields = resolveReferences(service, action.subject.type, action.fields ?? {}, aliasesFrom(parentEntries(service, root)));
|
|
247
|
-
const outcome = await adapters.perform(execute, fields === action.fields ? action : { ...action, fields }, performContext(service, root, rootCredentialFingerprint(
|
|
258
|
+
const outcome = await adapters.perform(execute, fields === action.fields ? action : { ...action, fields }, performContext(service, root, bound.sealed ? rootCredentialFingerprint(bound.sealed) : undefined));
|
|
248
259
|
// the vendor's answer, when the adapter returned one as fields, is what the landed copy holds
|
|
249
260
|
const answered = outcome.data !== null && typeof outcome.data === 'object' && !Array.isArray(outcome.data) ? outcome.data : {};
|
|
250
261
|
confirmAction({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/world-core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "The kernel of Volter World: one log per twin, branches as pointers, checkpoints, the fold that keeps a twin current, the head that performs a write against the vendor, references, and the git plane. A twin package builds on it; the runtime serves it.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
package/src/head.ts
CHANGED
|
@@ -229,15 +229,26 @@ export async function performEntries(opts: {
|
|
|
229
229
|
return run;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
/** The root a perform runs against: the sealed one, or — when the caller brings its own executor (a library holding
|
|
233
|
+
* the person's token in its own process) — the twin's root.json with no credential sealed at all. */
|
|
234
|
+
function performRoot(service: string, root: string | undefined, callerExecute: boolean): { sealed: BoundRoot | null; vendor: string } {
|
|
235
|
+
const head = headOf(service, root);
|
|
236
|
+
if (head.kind === 'real') return { sealed: head.root, vendor: vendorOf(head.root) };
|
|
237
|
+
const unsealed = callerExecute ? readRoot(service, root) : null;
|
|
238
|
+
if (!unsealed) throw new Error(`the ${service} twin has no root — nothing to perform against`);
|
|
239
|
+
return { sealed: null, vendor: service };
|
|
240
|
+
}
|
|
241
|
+
|
|
232
242
|
async function performNow(opts: Parameters<typeof performEntries>[0]): Promise<DeployReport> {
|
|
233
243
|
const { service, root } = opts;
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
const vendor = vendorOf(head.root);
|
|
244
|
+
const bound = performRoot(service, root, opts.execute !== undefined);
|
|
245
|
+
const vendor = bound.vendor;
|
|
237
246
|
const adapters = opts.adapters ?? stateSystemFor(vendor) ?? stateSystemFor(service);
|
|
238
247
|
if (!adapters?.perform) throw new Error(`the ${vendor} twin has no perform adapter — a protocol 2 pack names one in its descriptor and registers itself (registerPack)`);
|
|
239
|
-
|
|
240
|
-
const
|
|
248
|
+
// the caller's executor, or the one built over the sealed credential; an unsealed root has no other
|
|
249
|
+
const execute = opts.execute ?? buildRemoteExecute(validateRemoteOrigin(bound.sealed!.url, { allowInsecureLoopback: true }), await openRootCredential(bound.sealed!, vendor), authStrategyFor(vendor), getPack(vendor)?.hosts, { custody: rootCustody(bound.sealed!, vendor) });
|
|
250
|
+
// an unsealed root's World is where its state resolves (the root given, PROJECT_ROOT, or the working directory)
|
|
251
|
+
const checks = opts.checks ?? (await loadChecks(bound.sealed ? worldRootOf(bound.sealed) : worldPaths(service, root).root));
|
|
241
252
|
const deployable = deployableEntries(service, root);
|
|
242
253
|
const entries = opts.actionIds === undefined ? deployable : opts.actionIds.map((id) => deployable.find((a) => a.id === id)).filter((a): a is TwinAction => a !== undefined);
|
|
243
254
|
const report: DeployReport = { pushed: 0, deployed: [], skipped: [], replayed: [] };
|
|
@@ -260,7 +271,7 @@ async function performNow(opts: Parameters<typeof performEntries>[0]): Promise<D
|
|
|
260
271
|
// a declared reference to an adopted id is resolved before the pack sees the entry: the vendor is
|
|
261
272
|
// asked about #7, never the local #3 (docs/contributing/architecture.md#alias-aware-lookup-at-the-request-boundary)
|
|
262
273
|
const fields = resolveReferences(service, action.subject.type, action.fields ?? {}, aliasesFrom(parentEntries(service, root)));
|
|
263
|
-
const outcome = await adapters.perform(execute, fields === action.fields ? action : { ...action, fields }, performContext(service, root, rootCredentialFingerprint(
|
|
274
|
+
const outcome = await adapters.perform(execute, fields === action.fields ? action : { ...action, fields }, performContext(service, root, bound.sealed ? rootCredentialFingerprint(bound.sealed) : undefined));
|
|
264
275
|
// the vendor's answer, when the adapter returned one as fields, is what the landed copy holds
|
|
265
276
|
const answered = outcome.data !== null && typeof outcome.data === 'object' && !Array.isArray(outcome.data) ? (outcome.data as Record<string, unknown>) : {};
|
|
266
277
|
confirmAction({
|