githolon 0.100.6 → 0.101.1
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/cli.mjs +589 -79
- package/dist/dev-server.mjs +198 -54
- package/dist/framework/domain_nomos.package.usda +2 -2
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -329,6 +329,131 @@ var init_custody_transport = __esm({
|
|
|
329
329
|
}
|
|
330
330
|
});
|
|
331
331
|
|
|
332
|
+
// vendor/engine/managed-promotion.ts
|
|
333
|
+
function prepareManagedPromotion(report, candidateHash, domain, opts = {}) {
|
|
334
|
+
if (!report.sourceVerified || !report.complete || !report.evolve?.ok) {
|
|
335
|
+
const reason = !report.sourceVerified ? "the source ledger did not verify" : !report.complete ? "some historical premises could not be re-derived" : "the candidate fails deterministic schema evolution";
|
|
336
|
+
return { ok: false, stage: "preflight", report, error: `promotion refused: ${reason}` };
|
|
337
|
+
}
|
|
338
|
+
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
339
|
+
if (!report.promotable && !acceptanceReason) {
|
|
340
|
+
return {
|
|
341
|
+
ok: false,
|
|
342
|
+
stage: "acceptance",
|
|
343
|
+
report,
|
|
344
|
+
error: "exact history changes under the candidate; provide an acceptanceReason to make that business decision accountable"
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (!report.atStateRoot || !report.historyHash || !report.reportHash || !report.projection) {
|
|
348
|
+
return {
|
|
349
|
+
ok: false,
|
|
350
|
+
stage: "preflight",
|
|
351
|
+
report,
|
|
352
|
+
error: "the complete pre-flight report is missing its state, projection, or content proof"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const provedDomains = report.domains?.length ? report.domains : [report.domain];
|
|
356
|
+
if (!provedDomains.includes(domain)) {
|
|
357
|
+
return {
|
|
358
|
+
ok: false,
|
|
359
|
+
stage: "preflight",
|
|
360
|
+
report,
|
|
361
|
+
error: `the package-wide report does not cover the generated business area '${domain}'`
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
const reportEvidence = JSON.parse(JSON.stringify(report));
|
|
365
|
+
if (Array.isArray(reportEvidence.divergences)) {
|
|
366
|
+
for (const divergence of reportEvidence.divergences) {
|
|
367
|
+
if (divergence && typeof divergence === "object") {
|
|
368
|
+
delete divergence.atCommit;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const preflight = {
|
|
373
|
+
candidateHash,
|
|
374
|
+
// A package may be reached through any one of its generated domain clients. The
|
|
375
|
+
// kernel chooses one canonical domain for the private receipt so the exact same
|
|
376
|
+
// package/history proof has one identity regardless of that entry point.
|
|
377
|
+
domain: report.domain,
|
|
378
|
+
atHash: report.atHash,
|
|
379
|
+
atStateRoot: report.atStateRoot,
|
|
380
|
+
historyHash: report.historyHash,
|
|
381
|
+
reportHash: report.reportHash,
|
|
382
|
+
reportJson: JSON.stringify(reportEvidence),
|
|
383
|
+
complete: true,
|
|
384
|
+
evolveOk: true,
|
|
385
|
+
rawPromotable: report.promotable,
|
|
386
|
+
projectionEqual: report.projection.equal,
|
|
387
|
+
replayedIntents: report.replayedIntents,
|
|
388
|
+
candidateIntents: report.candidateIntents,
|
|
389
|
+
divergenceCount: report.divergences.length,
|
|
390
|
+
baselineRoot: report.projection.baselineRoot,
|
|
391
|
+
candidateRoot: report.projection.candidateRoot,
|
|
392
|
+
...!report.promotable && acceptanceReason ? { acceptanceReason } : {}
|
|
393
|
+
};
|
|
394
|
+
return {
|
|
395
|
+
ok: true,
|
|
396
|
+
stage: "ready",
|
|
397
|
+
report,
|
|
398
|
+
receiptId: `${RELEASE_RECEIPT_PREFIX}${report.reportHash}`,
|
|
399
|
+
payload: {
|
|
400
|
+
domainHash: candidateHash,
|
|
401
|
+
...opts.replaces ? { replaces: opts.replaces } : {},
|
|
402
|
+
retireReplaced: opts.retireReplaced ?? false,
|
|
403
|
+
...opts.dispositions ? { dispositions: opts.dispositions } : {},
|
|
404
|
+
preflight
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function prepareManagedRestoration(report, currentHash, priorHash, domain, opts = {}) {
|
|
409
|
+
if (!report.dispositions || typeof report.dispositions !== "object") {
|
|
410
|
+
return {
|
|
411
|
+
ok: false,
|
|
412
|
+
stage: "preflight",
|
|
413
|
+
report,
|
|
414
|
+
error: "restoration refused: the exact-history proof did not derive its predecessor dispositions"
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
418
|
+
const prepared = prepareManagedPromotion(report, priorHash, domain, {
|
|
419
|
+
dispositions: report.dispositions,
|
|
420
|
+
...acceptanceReason ? { acceptanceReason } : {}
|
|
421
|
+
});
|
|
422
|
+
if (!prepared.ok) {
|
|
423
|
+
return {
|
|
424
|
+
...prepared,
|
|
425
|
+
stage: prepared.stage === "acceptance" ? "acceptance" : "preflight"
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (!acceptanceReason) {
|
|
429
|
+
return {
|
|
430
|
+
ok: false,
|
|
431
|
+
stage: "acceptance",
|
|
432
|
+
report,
|
|
433
|
+
error: "restoring previous law needs a business reason even when historical outcomes are unchanged"
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
ok: true,
|
|
438
|
+
stage: "ready",
|
|
439
|
+
report,
|
|
440
|
+
receiptId: prepared.receiptId,
|
|
441
|
+
payload: {
|
|
442
|
+
candidateHash: currentHash,
|
|
443
|
+
priorHash,
|
|
444
|
+
dispositions: report.dispositions,
|
|
445
|
+
preflight: prepared.payload.preflight
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
var RELEASE_RECEIPT_PREFIX;
|
|
450
|
+
var init_managed_promotion = __esm({
|
|
451
|
+
"vendor/engine/managed-promotion.ts"() {
|
|
452
|
+
"use strict";
|
|
453
|
+
RELEASE_RECEIPT_PREFIX = "nomos-release-receipt:";
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
332
457
|
// vendor/engine/engine.ts
|
|
333
458
|
var engine_exports = {};
|
|
334
459
|
__export(engine_exports, {
|
|
@@ -360,6 +485,10 @@ __export(engine_exports, {
|
|
|
360
485
|
countTenantRowsByHome: () => countTenantRowsByHome,
|
|
361
486
|
createEngine: () => createEngine,
|
|
362
487
|
cryptoKeygen: () => cryptoKeygen,
|
|
488
|
+
cryptoOwnedDeviceRequest: () => cryptoOwnedDeviceRequest,
|
|
489
|
+
cryptoOwnedPrepareApproval: () => cryptoOwnedPrepareApproval,
|
|
490
|
+
cryptoOwnedPrepareRecovery: () => cryptoOwnedPrepareRecovery,
|
|
491
|
+
cryptoOwnedScopeKey: () => cryptoOwnedScopeKey,
|
|
363
492
|
cryptoSealField: () => cryptoSealField,
|
|
364
493
|
cryptoUnwrapKey: () => cryptoUnwrapKey,
|
|
365
494
|
cryptoWrapKey: () => cryptoWrapKey,
|
|
@@ -383,6 +512,8 @@ __export(engine_exports, {
|
|
|
383
512
|
flushDeferredProjections: () => flushDeferredProjections,
|
|
384
513
|
gitdirOf: () => gitdirOf,
|
|
385
514
|
globalAggregates: () => globalAggregates,
|
|
515
|
+
historyPreflight: () => historyPreflight,
|
|
516
|
+
historyRestorePreflight: () => historyRestorePreflight,
|
|
386
517
|
importCheckpoint: () => importCheckpoint,
|
|
387
518
|
ingestPackAsCustody: () => ingestPackAsCustody,
|
|
388
519
|
installPayload: () => installPayload,
|
|
@@ -405,9 +536,11 @@ __export(engine_exports, {
|
|
|
405
536
|
packBornChildren: () => packBornChildren,
|
|
406
537
|
packDelta: () => packDelta,
|
|
407
538
|
parseAttestedReadNeed: () => parseAttestedReadNeed,
|
|
539
|
+
pendingConflictSummary: () => pendingConflictSummary,
|
|
408
540
|
pendingConflicts: () => pendingConflicts,
|
|
409
541
|
placementDirectives: () => placementDirectives,
|
|
410
542
|
projectionStats: () => projectionStats,
|
|
543
|
+
promotePreflighted: () => promotePreflighted,
|
|
411
544
|
pushCheckpoint: () => pushCheckpoint,
|
|
412
545
|
pushShape: () => pushShape,
|
|
413
546
|
pushStagedCheckpoint: () => pushStagedCheckpoint,
|
|
@@ -425,6 +558,7 @@ __export(engine_exports, {
|
|
|
425
558
|
replicateIntents: () => replicateIntents,
|
|
426
559
|
repoArgOf: () => repoArgOf,
|
|
427
560
|
restoreCheckpointFromCustody: () => restoreCheckpointFromCustody,
|
|
561
|
+
restorePreviousPreflighted: () => restorePreviousPreflighted,
|
|
428
562
|
scopedReads: () => scopedReads,
|
|
429
563
|
sealAttestationBatches: () => sealAttestationBatches,
|
|
430
564
|
sealHomes: () => sealHomes,
|
|
@@ -435,6 +569,7 @@ __export(engine_exports, {
|
|
|
435
569
|
spatialBboxParams: () => spatialBboxParams,
|
|
436
570
|
spatialWithin: () => spatialWithin,
|
|
437
571
|
stageCheckpoint: () => stageCheckpoint,
|
|
572
|
+
stagePayload: () => stagePayload,
|
|
438
573
|
stats: () => stats,
|
|
439
574
|
sum: () => sum,
|
|
440
575
|
summaryCloseAgainstHeld: () => summaryCloseAgainstHeld,
|
|
@@ -1139,7 +1274,7 @@ async function replicateIntents(eng, ws, ledger, intents, { push = true } = {})
|
|
|
1139
1274
|
log("replicate-globals", { ws, replicated: replicated.length, skipped: skipped.length, refused: refused.length });
|
|
1140
1275
|
return { replicated, skipped, refused };
|
|
1141
1276
|
}
|
|
1142
|
-
async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null, shardRouting = null, clientBase = null
|
|
1277
|
+
async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null, shardRouting = null, clientBase = null } = {}) {
|
|
1143
1278
|
const main2 = await mainIntentIds(eng, ws);
|
|
1144
1279
|
const sessions = /* @__PURE__ */ new Map();
|
|
1145
1280
|
const deadLetters = [];
|
|
@@ -1206,8 +1341,8 @@ async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null,
|
|
|
1206
1341
|
}
|
|
1207
1342
|
const cap2 = summaryCtx ? beginSummaryCapture(eng, ws, summaryCtx, blob) : null;
|
|
1208
1343
|
const _tOffer = Date.now();
|
|
1209
|
-
const res = offerAdmit(eng, ws, blob, { defer:
|
|
1210
|
-
log("offer-admit-ms", { ws, ms: Date.now() - _tOffer, deferred:
|
|
1344
|
+
const res = offerAdmit(eng, ws, blob, { defer: false });
|
|
1345
|
+
log("offer-admit-ms", { ws, ms: Date.now() - _tOffer, deferred: false, ok: res.ok });
|
|
1211
1346
|
if (res.ok) {
|
|
1212
1347
|
if (intentId) main2.ids.add(intentId);
|
|
1213
1348
|
main2.oids.add(res.head);
|
|
@@ -1230,7 +1365,6 @@ async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null,
|
|
|
1230
1365
|
}
|
|
1231
1366
|
timings.sessions = sessions.size;
|
|
1232
1367
|
timings.intents = admittedTotal;
|
|
1233
|
-
if (admittedTotal && !summaryCtx) (eng.pendingProjection ??= /* @__PURE__ */ new Set()).add(ws);
|
|
1234
1368
|
if (deadLetters.length) {
|
|
1235
1369
|
try {
|
|
1236
1370
|
await materializeRefused(eng, ws, ledger, deadLetters);
|
|
@@ -1238,8 +1372,7 @@ async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null,
|
|
|
1238
1372
|
log("refused-materialize-failed", { ws, error: String(e).slice(0, 200) });
|
|
1239
1373
|
}
|
|
1240
1374
|
}
|
|
1241
|
-
|
|
1242
|
-
if (admittedTotal && !deferDurability) {
|
|
1375
|
+
if (admittedTotal) {
|
|
1243
1376
|
const sealDone = span("seal offered intents", "cseal", 1, { admitted: admittedTotal });
|
|
1244
1377
|
await commitAndPush(eng, ws, ledger);
|
|
1245
1378
|
sealDone();
|
|
@@ -1257,7 +1390,7 @@ async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null,
|
|
|
1257
1390
|
}
|
|
1258
1391
|
log("admit-intent-offers", { ws, sessions: sessions.size, admitted: admittedTotal, rejected: [...sessions.values()].reduce((n, s) => n + s.rejected.length, 0), resultPack: resultPackB64 ? "inline" : "none" });
|
|
1259
1392
|
const bornPacked = born.length ? packBornChildren(eng, born) : born;
|
|
1260
|
-
return { sessions: [...sessions.values()].map((s) => ({ ...s, ...s.skipped.length ? {} : { skipped: void 0 } })), main: head, deadLetters, timings, summary: summary ?? null, born: bornPacked, birthOutcomes, ...resultPackB64 ? { resultPackB64, resultBase: clientBase } : {}
|
|
1393
|
+
return { sessions: [...sessions.values()].map((s) => ({ ...s, ...s.skipped.length ? {} : { skipped: void 0 } })), main: head, deadLetters, timings, summary: summary ?? null, born: bornPacked, birthOutcomes, ...resultPackB64 ? { resultPackB64, resultBase: clientBase } : {} };
|
|
1261
1394
|
}
|
|
1262
1395
|
async function checkpointStateHash(eng, ws) {
|
|
1263
1396
|
const rows = query(eng, ws, "aggregatesByType", JSON.stringify({ __type: "NomosSummarySubtotal" }));
|
|
@@ -1415,6 +1548,9 @@ function mintId(eng, typeTag) {
|
|
|
1415
1548
|
function author(eng, ws, domain, directiveId, payload, controllerHash, opts = {}) {
|
|
1416
1549
|
const seq = eng.seq++;
|
|
1417
1550
|
const capPorts = { clock: { physical: Date.now(), logical: 0, replica: eng.replica }, rng: osEntropyBuffer(opts.rngDraws ?? 64) };
|
|
1551
|
+
if (opts.__nomosConflictSnapshots !== void 0 && opts.__nomosConflictSnapshots.length > 0) {
|
|
1552
|
+
capPorts.conflict_snapshots = opts.__nomosConflictSnapshots;
|
|
1553
|
+
}
|
|
1418
1554
|
if (opts.validFromEpoch !== void 0) capPorts.valid_from_epoch = opts.validFromEpoch;
|
|
1419
1555
|
if (opts.principalVerified !== void 0) {
|
|
1420
1556
|
capPorts.principal = opts.actor ?? "";
|
|
@@ -2214,6 +2350,120 @@ async function verifyChain(eng, ws, ledger) {
|
|
|
2214
2350
|
function verifyChainLocal(eng, ws) {
|
|
2215
2351
|
return JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "verifyChain" }), branch: BRANCH }, eng.STDERR));
|
|
2216
2352
|
}
|
|
2353
|
+
function historyPreflight(eng, ws, domain, candidateHash, atHash, dispositions) {
|
|
2354
|
+
return JSON.parse(call(eng.ex, "query", {
|
|
2355
|
+
repoArg: repoArgOf(ws),
|
|
2356
|
+
workspace: ws,
|
|
2357
|
+
branch: BRANCH,
|
|
2358
|
+
queryBytes: b64Json({
|
|
2359
|
+
op: "historyPreflight",
|
|
2360
|
+
domain,
|
|
2361
|
+
candidateHash,
|
|
2362
|
+
atHash,
|
|
2363
|
+
...dispositions ? { dispositions } : {}
|
|
2364
|
+
})
|
|
2365
|
+
}, eng.STDERR));
|
|
2366
|
+
}
|
|
2367
|
+
function historyRestorePreflight(eng, ws, domain, currentHash, priorHash, atHash, actor) {
|
|
2368
|
+
return JSON.parse(call(eng.ex, "query", {
|
|
2369
|
+
repoArg: repoArgOf(ws),
|
|
2370
|
+
workspace: ws,
|
|
2371
|
+
branch: BRANCH,
|
|
2372
|
+
queryBytes: b64Json({
|
|
2373
|
+
op: "historyPreflight",
|
|
2374
|
+
domain,
|
|
2375
|
+
candidateHash: priorHash,
|
|
2376
|
+
atHash,
|
|
2377
|
+
restorePreviousOf: currentHash,
|
|
2378
|
+
ackBy: actor
|
|
2379
|
+
})
|
|
2380
|
+
}, eng.STDERR));
|
|
2381
|
+
}
|
|
2382
|
+
function promotePreflighted(eng, ws, domain, candidateHash, opts = {}) {
|
|
2383
|
+
const actingPrincipal = opts.actor?.trim() || String(eng.installedBy || "").trim();
|
|
2384
|
+
if (!actingPrincipal && !opts.authToken) {
|
|
2385
|
+
return {
|
|
2386
|
+
ok: false,
|
|
2387
|
+
stage: "identity",
|
|
2388
|
+
error: "promotion needs the stateful client's current principal so its business decision is attributable"
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
const atHash = kgit.resolveRef(eng, gitdirOf(ws), BRANCH);
|
|
2392
|
+
if (!atHash) {
|
|
2393
|
+
return { ok: false, stage: "preflight", error: "workspace has no history to prove" };
|
|
2394
|
+
}
|
|
2395
|
+
let report;
|
|
2396
|
+
try {
|
|
2397
|
+
report = historyPreflight(eng, ws, domain, candidateHash, atHash, opts.dispositions);
|
|
2398
|
+
} catch (error) {
|
|
2399
|
+
return { ok: false, stage: "preflight", error: String(error?.message || error) };
|
|
2400
|
+
}
|
|
2401
|
+
const prepared = prepareManagedPromotion(report, candidateHash, domain, opts);
|
|
2402
|
+
if (!prepared.ok) return prepared;
|
|
2403
|
+
const {
|
|
2404
|
+
replaces: _replaces,
|
|
2405
|
+
retireReplaced: _retireReplaced,
|
|
2406
|
+
dispositions: _dispositions,
|
|
2407
|
+
acceptanceReason: _acceptance,
|
|
2408
|
+
...authorOpts
|
|
2409
|
+
} = opts;
|
|
2410
|
+
const result = author(eng, ws, "nomos", "promoteDomain", prepared.payload, eng.hashes.nomos, {
|
|
2411
|
+
...authorOpts,
|
|
2412
|
+
...actingPrincipal ? { actor: actingPrincipal } : {}
|
|
2413
|
+
});
|
|
2414
|
+
return result.ok ? { ...result, stage: "promoted", report, receiptId: prepared.receiptId } : { ...result, stage: "admission", report, receiptId: prepared.receiptId };
|
|
2415
|
+
}
|
|
2416
|
+
function restorePreviousPreflighted(eng, ws, domain, currentHash, opts = {}) {
|
|
2417
|
+
const actingPrincipal = opts.actor?.trim() || String(eng.installedBy || "").trim();
|
|
2418
|
+
if (!actingPrincipal) {
|
|
2419
|
+
return {
|
|
2420
|
+
ok: false,
|
|
2421
|
+
stage: "identity",
|
|
2422
|
+
error: "model restoration needs the stateful client's current principal so its business decision is attributable"
|
|
2423
|
+
};
|
|
2424
|
+
}
|
|
2425
|
+
const resolved = currentLaw(eng, ws)[domain];
|
|
2426
|
+
if (resolved !== currentHash) {
|
|
2427
|
+
return {
|
|
2428
|
+
ok: false,
|
|
2429
|
+
stage: "preflight",
|
|
2430
|
+
error: "the generated model is no longer current; nothing changed [nomos.rollout.restore-current-changed]"
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
const current = qById(eng, ws, `domain-installation:${currentHash}`)[0]?.data;
|
|
2434
|
+
const priorHash = typeof current?.["spec.supersedes"] === "string" ? current["spec.supersedes"] : "";
|
|
2435
|
+
if (!priorHash) {
|
|
2436
|
+
return {
|
|
2437
|
+
ok: false,
|
|
2438
|
+
stage: "preflight",
|
|
2439
|
+
error: "this model has no previous model to restore [nomos.rollout.restore-no-previous]"
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2442
|
+
const atHash = kgit.resolveRef(eng, gitdirOf(ws), BRANCH);
|
|
2443
|
+
if (!atHash) return { ok: false, stage: "preflight", error: "workspace has no history to prove" };
|
|
2444
|
+
let report;
|
|
2445
|
+
try {
|
|
2446
|
+
report = historyRestorePreflight(
|
|
2447
|
+
eng,
|
|
2448
|
+
ws,
|
|
2449
|
+
domain,
|
|
2450
|
+
currentHash,
|
|
2451
|
+
priorHash,
|
|
2452
|
+
atHash,
|
|
2453
|
+
actingPrincipal
|
|
2454
|
+
);
|
|
2455
|
+
} catch (error) {
|
|
2456
|
+
return { ok: false, stage: "preflight", error: String(error?.message || error) };
|
|
2457
|
+
}
|
|
2458
|
+
const prepared = prepareManagedRestoration(report, currentHash, priorHash, domain, opts);
|
|
2459
|
+
if (!prepared.ok) return prepared;
|
|
2460
|
+
const { acceptanceReason: _acceptance, ...authorOpts } = opts;
|
|
2461
|
+
const result = author(eng, ws, "nomos", "rollbackDomain", prepared.payload, eng.hashes.nomos, {
|
|
2462
|
+
...authorOpts,
|
|
2463
|
+
...actingPrincipal ? { actor: actingPrincipal } : {}
|
|
2464
|
+
});
|
|
2465
|
+
return result.ok ? { ...result, stage: "restored", report, receiptId: prepared.receiptId } : { ...result, stage: "admission", report, receiptId: prepared.receiptId };
|
|
2466
|
+
}
|
|
2217
2467
|
async function rebirthCompact(eng, ws, ledger, { reason = "", supersededAt = 0, parent = "" } = {}) {
|
|
2218
2468
|
const incWs = `${ws}__rebirth`;
|
|
2219
2469
|
try {
|
|
@@ -2526,26 +2776,89 @@ async function boot(eng, ws, ledger) {
|
|
|
2526
2776
|
);
|
|
2527
2777
|
}
|
|
2528
2778
|
async function deploy(eng, ws, ledger, usda, domainHash, dispositions, opts = {}) {
|
|
2529
|
-
const
|
|
2530
|
-
if (
|
|
2779
|
+
const existing = qById(eng, ws, `domain-installation:${domainHash}`);
|
|
2780
|
+
if (existing.length > 0) {
|
|
2781
|
+
const phase = String(existing[0]?.data?.["status.phase"] ?? "");
|
|
2782
|
+
return {
|
|
2783
|
+
head: kgit.resolveRef(eng, gitdirOf(ws), BRANCH),
|
|
2784
|
+
installation: existing,
|
|
2785
|
+
staged: phase === "Pending",
|
|
2786
|
+
alreadyInstalled: true
|
|
2787
|
+
};
|
|
2788
|
+
}
|
|
2789
|
+
const before = currentLaw(eng, ws);
|
|
2790
|
+
const tenantHashes = [...new Set(Object.values(before).filter(
|
|
2791
|
+
(hash) => typeof hash === "string" && hash !== eng.hashes.bootstrap && hash !== eng.hashes.nomos
|
|
2792
|
+
))];
|
|
2793
|
+
const upgrade = tenantHashes.length > 0;
|
|
2794
|
+
let supersedes = opts.supersedes?.trim() || void 0;
|
|
2795
|
+
if (supersedes !== void 0 && !tenantHashes.includes(supersedes)) {
|
|
2531
2796
|
throw new Error(
|
|
2532
|
-
`deploy-
|
|
2797
|
+
`deploy-predecessor-changed: the client named ${supersedes.slice(0, 12)}\u2026 as the current model, but this workspace no longer serves it. Refresh and deploy again; nothing was committed.`
|
|
2533
2798
|
);
|
|
2534
2799
|
}
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
const law = installedLaw(eng, ws);
|
|
2539
|
-
const currentLaw2 = law?.currentLaw ?? {};
|
|
2540
|
-
const stale = keys.filter((k) => currentLaw2[k] !== void 0 && currentLaw2[k] !== domainHash);
|
|
2541
|
-
if (stale.length > 0) {
|
|
2800
|
+
if (upgrade && supersedes === void 0) {
|
|
2801
|
+
if (tenantHashes.length === 1) supersedes = tenantHashes[0];
|
|
2802
|
+
else {
|
|
2542
2803
|
throw new Error(
|
|
2543
|
-
`deploy-
|
|
2804
|
+
`deploy-predecessor-ambiguous: this workspace currently serves ${tenantHashes.length} business-model packages. Nomos will not guess which one this candidate follows; use the generated deploy client, which binds the candidate to the current model before staging. Nothing was committed.`
|
|
2544
2805
|
);
|
|
2545
2806
|
}
|
|
2546
2807
|
}
|
|
2547
|
-
|
|
2548
|
-
|
|
2808
|
+
if (upgrade && dispositions && Object.keys(dispositions).length > 0) {
|
|
2809
|
+
throw new Error(
|
|
2810
|
+
"deploy-manual-evolution-refused: successor deployment no longer accepts caller-chosen schema dispositions. Schema evolution belongs to the candidate model's adoption proof; nothing was committed."
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
const directiveId = upgrade ? "stageDomain" : "installDomain";
|
|
2814
|
+
const payload = upgrade ? stagePayload(domainHash, usda, eng.installedBy, supersedes) : installPayload(domainHash, usda, eng.installedBy, dispositions);
|
|
2815
|
+
const result = author(eng, ws, "nomos", directiveId, payload, eng.hashes.nomos, {
|
|
2816
|
+
actor: opts.actor ?? "",
|
|
2817
|
+
...opts.authToken ? { authToken: opts.authToken } : {}
|
|
2818
|
+
});
|
|
2819
|
+
if (result.ok === false) {
|
|
2820
|
+
unmount(eng, ws);
|
|
2821
|
+
throw new Error(
|
|
2822
|
+
`deploy-refused: ${upgrade ? "staging" : "installing"} ${domainHash.slice(0, 12)}\u2026 was REFUSED by the one gate (custody unchanged): ${result.error ?? "unknown refusal"}`
|
|
2823
|
+
);
|
|
2824
|
+
}
|
|
2825
|
+
try {
|
|
2826
|
+
const installation = qById(eng, ws, `domain-installation:${domainHash}`);
|
|
2827
|
+
if (upgrade) {
|
|
2828
|
+
const phase = String(installation[0]?.data?.["status.phase"] ?? "");
|
|
2829
|
+
if (phase !== "Pending") {
|
|
2830
|
+
throw new Error(
|
|
2831
|
+
`deploy-did-not-stage: candidate ${domainHash.slice(0, 12)}\u2026 admitted but its lifecycle phase is '${phase || "missing"}', not Pending. Custody was not pushed.`
|
|
2832
|
+
);
|
|
2833
|
+
}
|
|
2834
|
+
const after = currentLaw(eng, ws);
|
|
2835
|
+
const moved = Object.entries(before).filter(([key, hash]) => after[key] !== hash);
|
|
2836
|
+
if (moved.length > 0 || Object.values(after).includes(domainHash)) {
|
|
2837
|
+
throw new Error(
|
|
2838
|
+
`deploy-activated-candidate: staging ${domainHash.slice(0, 12)}\u2026 changed served law (${moved.map(([key]) => key).join(", ") || "candidate became current"}). Nomos refuses to persist an upgrade that bypassed model.adopt().`
|
|
2839
|
+
);
|
|
2840
|
+
}
|
|
2841
|
+
await commitAndPush(eng, ws, ledger);
|
|
2842
|
+
return { head: result.head, installation, staged: true, supersedes };
|
|
2843
|
+
}
|
|
2844
|
+
const law = installedLaw(eng, ws);
|
|
2845
|
+
const installed = (law?.domains ?? []).find((row) => row?.domainHash === domainHash);
|
|
2846
|
+
const keys = installed?.domainKeys ?? installation[0]?.data?.domainKeys ?? installation[0]?.domainKeys ?? [];
|
|
2847
|
+
if (keys.length > 0) {
|
|
2848
|
+
const currentLaw2 = law?.currentLaw ?? {};
|
|
2849
|
+
const stale = keys.filter((k) => currentLaw2[k] !== domainHash);
|
|
2850
|
+
if (stale.length > 0) {
|
|
2851
|
+
throw new Error(
|
|
2852
|
+
`deploy-did-not-advance: the install of ${domainHash.slice(0, 12)}\u2026 ADMITTED but the workspace's current law still serves ${stale.map((k) => `'${k}' from ${String(currentLaw2[k]).slice(0, 12)}\u2026`).join(", ")} \u2014 refusing (custody unchanged) instead of a silent no-op. This usually means the existing installation's era/lineage prevents supersession: run \`githolon deploy --dry-run=evolve\` for the gate's verdict, supply #58 dispositions for a true removal/retype, or re-forge the workspace onto the current lineage.`
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
await commitAndPush(eng, ws, ledger);
|
|
2857
|
+
return { head: result.head, installation, staged: false };
|
|
2858
|
+
} catch (error) {
|
|
2859
|
+
unmount(eng, ws);
|
|
2860
|
+
throw error;
|
|
2861
|
+
}
|
|
2549
2862
|
}
|
|
2550
2863
|
function snapshot(eng, ws) {
|
|
2551
2864
|
const wsDir = dirOf(eng.preopen.dir.contents.get("ws")).contents.get(ws);
|
|
@@ -2645,13 +2958,14 @@ function sealAttestationBatches(eng, ws, domain, controllerHash, opts = {}) {
|
|
|
2645
2958
|
}
|
|
2646
2959
|
return outcomes;
|
|
2647
2960
|
}
|
|
2648
|
-
var enc3, dec3, BRANCH, RESULT_PACK_INLINE_MAX, dirOf, repoArgOf, gitdirOf, unpack, log, repoArgOfGitdir, bytesFromB64, kgit, installPayload, routeTagHexOfHomeKey, SUMMARY_SEP, summaryKey, splitSummaryKey, NOMOS_SHARD_ROWS_READ, groupOf, tallyOf, isExtremumRead, extremumMonotone, CKPT_REF, pushVia, fullRef, applyPackInto, custodyLsRefs, qById, query, check, expand, cryptoSealField, cryptoKeygen, authorKeygen, eraCertSign, delegationCertSign, attestationSign, attestedRead, certSign, cryptoWrapKey, cryptoUnwrapKey, readPosture, count, sum, pendingConflicts, spatialBboxParams, spatialWithin, extremum, nomosActive, refusedRefName, outboxRefName, GENESIS_WARRANT_ID, isWarranted, projectionStats;
|
|
2961
|
+
var enc3, dec3, BRANCH, RESULT_PACK_INLINE_MAX, dirOf, repoArgOf, gitdirOf, unpack, log, repoArgOfGitdir, bytesFromB64, kgit, installPayload, stagePayload, routeTagHexOfHomeKey, SUMMARY_SEP, summaryKey, splitSummaryKey, NOMOS_SHARD_ROWS_READ, groupOf, tallyOf, isExtremumRead, extremumMonotone, CKPT_REF, pushVia, fullRef, applyPackInto, custodyLsRefs, qById, query, check, expand, cryptoSealField, cryptoOwnedScopeKey, cryptoOwnedDeviceRequest, cryptoOwnedPrepareApproval, cryptoOwnedPrepareRecovery, cryptoKeygen, authorKeygen, eraCertSign, delegationCertSign, attestationSign, attestedRead, certSign, cryptoWrapKey, cryptoUnwrapKey, readPosture, count, sum, pendingConflicts, pendingConflictSummary, spatialBboxParams, spatialWithin, extremum, nomosActive, refusedRefName, outboxRefName, GENESIS_WARRANT_ID, isWarranted, projectionStats;
|
|
2649
2962
|
var init_engine = __esm({
|
|
2650
2963
|
"vendor/engine/engine.ts"() {
|
|
2651
2964
|
"use strict";
|
|
2652
2965
|
init_git_fs();
|
|
2653
2966
|
init_tree();
|
|
2654
2967
|
init_custody_transport();
|
|
2968
|
+
init_managed_promotion();
|
|
2655
2969
|
enc3 = new TextEncoder();
|
|
2656
2970
|
dec3 = new TextDecoder();
|
|
2657
2971
|
BRANCH = "main";
|
|
@@ -2697,6 +3011,14 @@ var init_engine = __esm({
|
|
|
2697
3011
|
}, eng.STDERR)).oid
|
|
2698
3012
|
};
|
|
2699
3013
|
installPayload = (hash, usda, installedBy, dispositions) => ({ domainHash: hash, packageUsda: usda, installedBy, dependencies: [], finalizers: [], ...dispositions ? { dispositions } : {} });
|
|
3014
|
+
stagePayload = (hash, usda, installedBy, supersedes) => ({
|
|
3015
|
+
domainHash: hash,
|
|
3016
|
+
packageUsda: usda,
|
|
3017
|
+
installedBy,
|
|
3018
|
+
dependencies: [],
|
|
3019
|
+
...supersedes ? { supersedes } : {},
|
|
3020
|
+
finalizers: []
|
|
3021
|
+
});
|
|
2700
3022
|
routeTagHexOfHomeKey = async (homeKey) => (await sha256hex(`nomos-route:${homeKey}`)).slice(0, 12);
|
|
2701
3023
|
SUMMARY_SEP = "";
|
|
2702
3024
|
summaryKey = (readId, group) => `${readId}${SUMMARY_SEP}${group}`;
|
|
@@ -2727,6 +3049,105 @@ var init_engine = __esm({
|
|
|
2727
3049
|
check = (eng, ws, object, relation, subject) => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "check", object, relation, subject }), branch: BRANCH }, eng.STDERR));
|
|
2728
3050
|
expand = (eng, ws, object, relation) => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "expand", object, relation }), branch: BRANCH }, eng.STDERR));
|
|
2729
3051
|
cryptoSealField = (eng, { scopeKey, scope, epoch, aggSid, fieldSid, plaintext }) => JSON.parse(call(eng.ex, "query", { queryBytes: b64Json({ op: "cryptoSealField", scopeKey, scope, epoch, aggSid, fieldSid, plaintext }) }, eng.STDERR)).envelope;
|
|
3052
|
+
cryptoOwnedScopeKey = (eng, workspace, authorSecret, scope, principal = "", requireSeat = true, record, recordEpoch = 0, recordWrap) => {
|
|
3053
|
+
const recordObject = record === void 0 ? void 0 : `${record.type}:${record.id}`;
|
|
3054
|
+
const derived = JSON.parse(call(eng.ex, "query", {
|
|
3055
|
+
queryBytes: b64Json({
|
|
3056
|
+
op: "cryptoOwnedScopeKey",
|
|
3057
|
+
workspace,
|
|
3058
|
+
principal,
|
|
3059
|
+
authorSecret,
|
|
3060
|
+
scope,
|
|
3061
|
+
...recordObject === void 0 ? {} : { recordObject, recordEpoch },
|
|
3062
|
+
...recordWrap === void 0 ? {} : { recordWrap }
|
|
3063
|
+
})
|
|
3064
|
+
}, eng.STDERR));
|
|
3065
|
+
const ownedKeySubject = String(derived.ownedKeySubject || "");
|
|
3066
|
+
if (!requireSeat) {
|
|
3067
|
+
return {
|
|
3068
|
+
scope: String(derived.scope || scope),
|
|
3069
|
+
epoch: Number(derived.epoch) || 0,
|
|
3070
|
+
key: String(derived.scopeKey || ""),
|
|
3071
|
+
ownedKeySubject,
|
|
3072
|
+
ownedCustody: typeof derived.ownedCustody === "string" ? derived.ownedCustody : void 0,
|
|
3073
|
+
keyCommitment: typeof derived.keyCommitment === "string" ? derived.keyCommitment : void 0,
|
|
3074
|
+
principalWrappingPublic: typeof derived.principalWrappingPublic === "string" ? derived.principalWrappingPublic : void 0
|
|
3075
|
+
};
|
|
3076
|
+
}
|
|
3077
|
+
if (principal) {
|
|
3078
|
+
let hex = "";
|
|
3079
|
+
for (const byte of enc3.encode(principal)) hex += byte.toString(16).padStart(2, "0");
|
|
3080
|
+
const object = `nomos-owned-principal:${hex || "00"}`;
|
|
3081
|
+
const rows = qById(eng, workspace, `reltuple-${object}-nomos_internal_owned_device_key_7c1f5e`);
|
|
3082
|
+
const row = Array.isArray(rows) ? rows[0] : rows?.rows?.[0];
|
|
3083
|
+
const leaves = row?.data?.subjects ?? row?.subjects ?? {};
|
|
3084
|
+
const leaf = (raw) => {
|
|
3085
|
+
if (raw && typeof raw === "object") return raw;
|
|
3086
|
+
try {
|
|
3087
|
+
return typeof raw === "string" ? JSON.parse(raw) : {};
|
|
3088
|
+
} catch {
|
|
3089
|
+
return {};
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
const active = Object.entries(leaves).filter(([, raw]) => leaf(raw).status === "active").map(([subject]) => subject);
|
|
3093
|
+
if (active.length === 0 && Object.keys(leaves).length === 0) {
|
|
3094
|
+
return {
|
|
3095
|
+
scope: String(derived.scope || scope),
|
|
3096
|
+
epoch: Number(derived.epoch) || 0,
|
|
3097
|
+
key: String(derived.scopeKey || ""),
|
|
3098
|
+
ownedKeySubject,
|
|
3099
|
+
ownedCustody: typeof derived.ownedCustody === "string" ? derived.ownedCustody : void 0,
|
|
3100
|
+
keyCommitment: typeof derived.keyCommitment === "string" ? derived.keyCommitment : void 0,
|
|
3101
|
+
principalWrappingPublic: typeof derived.principalWrappingPublic === "string" ? derived.principalWrappingPublic : void 0
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
if (!active.includes(ownedKeySubject)) {
|
|
3105
|
+
throw new Error(
|
|
3106
|
+
"this device is waiting for approval \u2014 approve its opaque request on an already-working device"
|
|
3107
|
+
);
|
|
3108
|
+
}
|
|
3109
|
+
const custody = String(leaf(leaves[ownedKeySubject]).ownedCustody || "");
|
|
3110
|
+
if (!custody) throw new Error("the approved device has no owned-data handoff");
|
|
3111
|
+
const opened = JSON.parse(call(eng.ex, "query", {
|
|
3112
|
+
queryBytes: b64Json({
|
|
3113
|
+
op: "cryptoOwnedScopeKey",
|
|
3114
|
+
workspace,
|
|
3115
|
+
principal,
|
|
3116
|
+
authorSecret,
|
|
3117
|
+
scope,
|
|
3118
|
+
ownedCustody: custody,
|
|
3119
|
+
...recordObject === void 0 ? {} : { recordObject, recordEpoch },
|
|
3120
|
+
...recordWrap === void 0 ? {} : { recordWrap }
|
|
3121
|
+
})
|
|
3122
|
+
}, eng.STDERR));
|
|
3123
|
+
return {
|
|
3124
|
+
scope: String(opened.scope || scope),
|
|
3125
|
+
epoch: Number(opened.epoch) || 0,
|
|
3126
|
+
key: String(opened.scopeKey || ""),
|
|
3127
|
+
ownedKeySubject,
|
|
3128
|
+
keyCommitment: typeof opened.keyCommitment === "string" ? opened.keyCommitment : void 0,
|
|
3129
|
+
principalWrappingPublic: typeof opened.principalWrappingPublic === "string" ? opened.principalWrappingPublic : void 0
|
|
3130
|
+
};
|
|
3131
|
+
}
|
|
3132
|
+
return {
|
|
3133
|
+
scope: String(derived.scope || scope),
|
|
3134
|
+
epoch: Number(derived.epoch) || 0,
|
|
3135
|
+
key: String(derived.scopeKey || ""),
|
|
3136
|
+
ownedKeySubject,
|
|
3137
|
+
ownedCustody: typeof derived.ownedCustody === "string" ? derived.ownedCustody : void 0,
|
|
3138
|
+
keyCommitment: typeof derived.keyCommitment === "string" ? derived.keyCommitment : void 0,
|
|
3139
|
+
principalWrappingPublic: typeof derived.principalWrappingPublic === "string" ? derived.principalWrappingPublic : void 0
|
|
3140
|
+
};
|
|
3141
|
+
};
|
|
3142
|
+
cryptoOwnedDeviceRequest = (eng, workspace, principal, authorSecret, scope) => String(JSON.parse(call(eng.ex, "query", {
|
|
3143
|
+
queryBytes: b64Json({ op: "cryptoOwnedDeviceRequest", workspace, principal, authorSecret, scope })
|
|
3144
|
+
}, eng.STDERR)).request || "");
|
|
3145
|
+
cryptoOwnedPrepareApproval = (eng, args) => JSON.parse(call(eng.ex, "query", {
|
|
3146
|
+
queryBytes: b64Json({ op: "cryptoOwnedPrepareApproval", ...args })
|
|
3147
|
+
}, eng.STDERR));
|
|
3148
|
+
cryptoOwnedPrepareRecovery = (eng, args) => JSON.parse(call(eng.ex, "query", {
|
|
3149
|
+
queryBytes: b64Json({ op: "cryptoOwnedPrepareRecovery", ...args })
|
|
3150
|
+
}, eng.STDERR));
|
|
2730
3151
|
cryptoKeygen = (eng) => JSON.parse(call(eng.ex, "query", { queryBytes: b64Json({ op: "cryptoKeygen" }) }, eng.STDERR));
|
|
2731
3152
|
authorKeygen = (eng) => JSON.parse(call(eng.ex, "query", { queryBytes: b64Json({ op: "authorKeygen" }) }, eng.STDERR));
|
|
2732
3153
|
eraCertSign = (eng, args) => JSON.parse(call(eng.ex, "query", { queryBytes: b64Json({ op: "eraCertSign", ...args }) }, eng.STDERR));
|
|
@@ -2774,7 +3195,8 @@ var init_engine = __esm({
|
|
|
2774
3195
|
readPosture = (eng, ws, principal = "", authToken = "", nowUnix = 0) => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "readPosture", authToken, nowUnix }), principal, branch: BRANCH }, eng.STDERR));
|
|
2775
3196
|
count = (eng, ws, countId, groupKey, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "count", countId, groupKey }), principal, branch: BRANCH }, eng.STDERR));
|
|
2776
3197
|
sum = (eng, ws, sumId, groupKey, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "sum", sumId, groupKey }), principal, branch: BRANCH }, eng.STDERR));
|
|
2777
|
-
pendingConflicts = (eng, ws, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "pendingConflicts" }), principal, branch: BRANCH }, eng.STDERR));
|
|
3198
|
+
pendingConflicts = (eng, ws, principal = "", aggregateType = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "pendingConflicts", aggregateType }), principal, branch: BRANCH }, eng.STDERR));
|
|
3199
|
+
pendingConflictSummary = (eng, ws, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "pendingConflictSummary" }), principal, branch: BRANCH }, eng.STDERR));
|
|
2778
3200
|
spatialBboxParams = (bbox) => {
|
|
2779
3201
|
const minX = bbox.minX ?? bbox.minLng, minY = bbox.minY ?? bbox.minLat, maxX = bbox.maxX ?? bbox.maxLng, maxY = bbox.maxY ?? bbox.maxLat;
|
|
2780
3202
|
return { minX, minY, maxX, maxY, minLng: minX, minLat: minY, maxLng: maxX, maxLat: maxY };
|
|
@@ -2820,15 +3242,28 @@ async function fetchJsonCached(url, cacheFile) {
|
|
|
2820
3242
|
}
|
|
2821
3243
|
}
|
|
2822
3244
|
async function fetchRuntime(cloud, kind = "production") {
|
|
2823
|
-
const cache = join2(configDir(), "runtime");
|
|
3245
|
+
const cache = process.env["NOMOS_OFFLINE_RUNTIME"] || join2(configDir(), "runtime");
|
|
2824
3246
|
let wasmBytes;
|
|
2825
3247
|
const wasmName = kind === "test-mint" ? "holon-testmint.wasm" : "holon.wasm";
|
|
2826
3248
|
const wasmUrl = kind === "test-mint" ? "holon-testmint.wasm" : "holon.wasm";
|
|
2827
3249
|
const wasmCache = join2(cache, wasmName);
|
|
3250
|
+
const packagesCache = join2(cache, "packages.json");
|
|
3251
|
+
const refresh = String(process.env["NOMOS_RUNTIME_REFRESH"] || "auto").toLowerCase();
|
|
3252
|
+
if (refresh === "never") {
|
|
3253
|
+
if (!existsSync2(wasmCache) || !existsSync2(packagesCache)) {
|
|
3254
|
+
throw new Error(
|
|
3255
|
+
`offline runtime cache missing at ${cache} (${wasmName} + packages.json); build or warm that exact runtime before running with NOMOS_RUNTIME_REFRESH=never`
|
|
3256
|
+
);
|
|
3257
|
+
}
|
|
3258
|
+
return {
|
|
3259
|
+
wasmBytes: readFileSync(wasmCache),
|
|
3260
|
+
packages: JSON.parse(readFileSync(packagesCache, "utf8"))
|
|
3261
|
+
};
|
|
3262
|
+
}
|
|
2828
3263
|
const localWasm = process.env["NOMOS_LOCAL_WASM"];
|
|
2829
3264
|
if (localWasm) {
|
|
2830
3265
|
const bytes = readFileSync(localWasm);
|
|
2831
|
-
const packages2 = await fetchJsonCached(`${cloud}/v1/runtime/packages`,
|
|
3266
|
+
const packages2 = await fetchJsonCached(`${cloud}/v1/runtime/packages`, packagesCache);
|
|
2832
3267
|
return { wasmBytes: bytes, packages: packages2 };
|
|
2833
3268
|
}
|
|
2834
3269
|
try {
|
|
@@ -2841,7 +3276,7 @@ async function fetchRuntime(cloud, kind = "production") {
|
|
|
2841
3276
|
if (!existsSync2(wasmCache)) throw e;
|
|
2842
3277
|
wasmBytes = readFileSync(wasmCache);
|
|
2843
3278
|
}
|
|
2844
|
-
const packages = await fetchJsonCached(`${cloud}/v1/runtime/packages`,
|
|
3279
|
+
const packages = await fetchJsonCached(`${cloud}/v1/runtime/packages`, packagesCache);
|
|
2845
3280
|
return { wasmBytes, packages };
|
|
2846
3281
|
}
|
|
2847
3282
|
function atomicWriteRuntime(target, data) {
|
|
@@ -4980,14 +5415,14 @@ function negotiateDeployRoute(caps, opts) {
|
|
|
4980
5415
|
if (opts.signed) {
|
|
4981
5416
|
if (caps.offerLane === false) {
|
|
4982
5417
|
return {
|
|
4983
|
-
fail: `${caps.cloud}
|
|
4984
|
-
\u2192
|
|
5418
|
+
fail: `${caps.cloud} cannot accept an authenticated deployment for this workspace \u2014 POST /v2/workspaces/${opts.ws}/${opts.route.domain}/${opts.route.directiveId} is not routed because the workspace serves no self-describing gateway.
|
|
5419
|
+
\u2192 target a current Nomos cloud that supports attributed deployment.`
|
|
4985
5420
|
};
|
|
4986
5421
|
}
|
|
4987
5422
|
if (caps.offerLane === true && caps.routesTarget === false) {
|
|
4988
5423
|
return {
|
|
4989
|
-
fail: `${caps.cloud} serves the offer gateway for ${opts.ws}, but its OpenAPI does not name the route ${opts.route.domain}/${opts.route.directiveId} \u2014 the ${opts.route.domain} controller is not installed here, so
|
|
4990
|
-
\u2192 confirm the workspace is born and
|
|
5424
|
+
fail: `${caps.cloud} serves the offer gateway for ${opts.ws}, but its OpenAPI does not name the route ${opts.route.domain}/${opts.route.directiveId} \u2014 the ${opts.route.domain} controller is not installed here, so the lifecycle request would 404.
|
|
5425
|
+
\u2192 confirm the workspace is born and its current Nomos controller is installed.`
|
|
4991
5426
|
};
|
|
4992
5427
|
}
|
|
4993
5428
|
if (opts.sealedSizeChars > INLINE_OFFER_CAP_CHARS && caps.stage === false) {
|
|
@@ -5065,7 +5500,7 @@ function domainKeysOf(body) {
|
|
|
5065
5500
|
function packageHashOf(packageUsda) {
|
|
5066
5501
|
return createHash2("sha256").update(Buffer.from(packageUsda, "utf8")).digest("hex");
|
|
5067
5502
|
}
|
|
5068
|
-
function resolveDeployPlan(domainKeys, currentLaw2, targetHash
|
|
5503
|
+
function resolveDeployPlan(domainKeys, currentLaw2, targetHash) {
|
|
5069
5504
|
const decisions = [];
|
|
5070
5505
|
const priors = /* @__PURE__ */ new Set();
|
|
5071
5506
|
for (const key of domainKeys) {
|
|
@@ -5074,21 +5509,18 @@ function resolveDeployPlan(domainKeys, currentLaw2, targetHash, opts = {}) {
|
|
|
5074
5509
|
decisions.push({ key, action: "first" });
|
|
5075
5510
|
} else if (currentHash === targetHash) {
|
|
5076
5511
|
decisions.push({ key, currentHash, action: "idempotent" });
|
|
5077
|
-
} else if (opts.keepBeside === true) {
|
|
5078
|
-
decisions.push({ key, currentHash, action: "keep-beside" });
|
|
5079
5512
|
} else {
|
|
5080
|
-
decisions.push({ key, currentHash, action: "
|
|
5513
|
+
decisions.push({ key, currentHash, action: "successor" });
|
|
5081
5514
|
priors.add(currentHash);
|
|
5082
5515
|
}
|
|
5083
5516
|
}
|
|
5084
|
-
const
|
|
5517
|
+
const predecessorCandidates = [...priors];
|
|
5085
5518
|
const idempotent = domainKeys.length > 0 && decisions.every((d) => d.action === "idempotent");
|
|
5086
5519
|
return {
|
|
5087
5520
|
decisions,
|
|
5088
|
-
...
|
|
5089
|
-
retireReplaced: opts.retireReplaced === true,
|
|
5521
|
+
...predecessorCandidates.length > 0 ? { supersedes: predecessorCandidates[0] } : {},
|
|
5090
5522
|
idempotent,
|
|
5091
|
-
|
|
5523
|
+
predecessorCandidates
|
|
5092
5524
|
};
|
|
5093
5525
|
}
|
|
5094
5526
|
function describeDeployPlan(plan, targetHash) {
|
|
@@ -5097,10 +5529,8 @@ function describeDeployPlan(plan, targetHash) {
|
|
|
5097
5529
|
switch (d.action) {
|
|
5098
5530
|
case "first":
|
|
5099
5531
|
return ` ${d.key}: ${t} installed (first)`;
|
|
5100
|
-
case "
|
|
5101
|
-
return ` ${d.key}: ${t}
|
|
5102
|
-
case "keep-beside":
|
|
5103
|
-
return ` ${d.key}: ${t} kept beside ${short(d.currentHash)}`;
|
|
5532
|
+
case "successor":
|
|
5533
|
+
return ` ${d.key}: ${t} is the candidate after ${short(d.currentHash)}`;
|
|
5104
5534
|
case "idempotent":
|
|
5105
5535
|
return ` ${d.key}: unchanged \u2014 ${t} is already active`;
|
|
5106
5536
|
}
|
|
@@ -5571,7 +6001,7 @@ async function wsCreate(name, opts) {
|
|
|
5571
6001
|
return 1;
|
|
5572
6002
|
}
|
|
5573
6003
|
out4(`\u2713 createWorkspace '${name}' requested via signed governance offer to ${opts.via} on ${cloud}`);
|
|
5574
|
-
out4(` the worker provisions it on first touch;
|
|
6004
|
+
out4(` the worker provisions it on first touch; then run githolon deploy ${name}`);
|
|
5575
6005
|
out4(` (want the direct birth instead? drop --via: githolon ws create ${name})`);
|
|
5576
6006
|
return 0;
|
|
5577
6007
|
}
|
|
@@ -5614,7 +6044,7 @@ async function wsCreate(name, opts) {
|
|
|
5614
6044
|
}
|
|
5615
6045
|
if (opts.principal !== void 0) setPrincipal(opts.principal);
|
|
5616
6046
|
out4(`\u2713 workspace ${name} created on ${cloud}`);
|
|
5617
|
-
out4(` deploy
|
|
6047
|
+
out4(` deploy its first model: githolon deploy ${name}`);
|
|
5618
6048
|
return 0;
|
|
5619
6049
|
}
|
|
5620
6050
|
async function wsStatus(name, opts) {
|
|
@@ -5816,14 +6246,18 @@ async function deploy2(ws, opts) {
|
|
|
5816
6246
|
try {
|
|
5817
6247
|
const body = readDeployBody3(file);
|
|
5818
6248
|
targetHash = packageHashOf2(body.packageUsda);
|
|
5819
|
-
plan = resolveDeployPlan2(domainKeysOf2(body), currentLaw2, targetHash
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
}
|
|
5824
|
-
|
|
5825
|
-
|
|
6249
|
+
plan = resolveDeployPlan2(domainKeysOf2(body), currentLaw2, targetHash);
|
|
6250
|
+
} catch (error) {
|
|
6251
|
+
err4(`deploy '${ws}' needs the current generated deploy body: ${error.message}`);
|
|
6252
|
+
return 1;
|
|
6253
|
+
}
|
|
6254
|
+
if ((plan?.predecessorCandidates.length ?? 0) > 1) {
|
|
6255
|
+
err4(
|
|
6256
|
+
`deploy '${ws}' refused: this candidate spans ${plan.predecessorCandidates.length} different current models; Nomos will not guess one predecessor. Compile one coherent workspace model and try again.`
|
|
6257
|
+
);
|
|
6258
|
+
return 1;
|
|
5826
6259
|
}
|
|
6260
|
+
let expectsPending = plan !== void 0 && plan.predecessorCandidates.length === 1 && !plan.idempotent;
|
|
5827
6261
|
const principal = opts.principal ?? activePrincipal();
|
|
5828
6262
|
const signed = opts.principal !== void 0 || principal !== void 0 && getDeviceKey(principal) !== void 0;
|
|
5829
6263
|
let phaseSuffix = "";
|
|
@@ -5842,8 +6276,14 @@ async function deploy2(ws, opts) {
|
|
|
5842
6276
|
return 1;
|
|
5843
6277
|
}
|
|
5844
6278
|
const targetHash2 = createHash3("sha256").update(Buffer.from(packageUsda, "utf8")).digest("hex");
|
|
6279
|
+
if (expectsPending && body.dispositions !== void 0 && body.dispositions !== null) {
|
|
6280
|
+
err4(
|
|
6281
|
+
`deploy '${ws}' refused: successor models cannot carry caller-chosen schema dispositions; evolution must be proved by model.adopt(), not smuggled into deployment`
|
|
6282
|
+
);
|
|
6283
|
+
return 1;
|
|
6284
|
+
}
|
|
5845
6285
|
const { probeCloudCapabilities: probeCloudCapabilities2, negotiateDeployRoute: negotiateDeployRoute2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
|
|
5846
|
-
const route = { domain: "nomos", directiveId: "installDomain" };
|
|
6286
|
+
const route = { domain: "nomos", directiveId: expectsPending ? "stageDomain" : "installDomain" };
|
|
5847
6287
|
const caps = await probeCloudCapabilities2(cloud, ws, route);
|
|
5848
6288
|
const refusal = negotiateDeployRoute2(caps, { signed: true, ws, sealedSizeChars: packageUsda.length, route });
|
|
5849
6289
|
if (refusal !== void 0) {
|
|
@@ -5855,17 +6295,16 @@ async function deploy2(ws, opts) {
|
|
|
5855
6295
|
let v;
|
|
5856
6296
|
try {
|
|
5857
6297
|
const who = resolveGovernancePrincipal2(opts);
|
|
5858
|
-
const
|
|
6298
|
+
const lifecyclePayload = {
|
|
5859
6299
|
domainHash: targetHash2,
|
|
5860
6300
|
packageUsda,
|
|
5861
6301
|
installedBy: `user:${who}`,
|
|
5862
6302
|
dependencies: [],
|
|
5863
6303
|
finalizers: [],
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
...body.dispositions !== void 0 && body.dispositions !== null ? { dispositions: body.dispositions } : {}
|
|
6304
|
+
...expectsPending && plan?.supersedes !== void 0 ? { supersedes: plan.supersedes } : {},
|
|
6305
|
+
...!expectsPending && body.dispositions !== void 0 && body.dispositions !== null ? { dispositions: body.dispositions } : {}
|
|
5867
6306
|
};
|
|
5868
|
-
v = await signAndPostOffer2(ws, "nomos",
|
|
6307
|
+
v = await signAndPostOffer2(ws, "nomos", route.directiveId, lifecyclePayload, opts);
|
|
5869
6308
|
} catch (e) {
|
|
5870
6309
|
err4(e.message);
|
|
5871
6310
|
return 1;
|
|
@@ -5887,7 +6326,7 @@ async function deploy2(ws, opts) {
|
|
|
5887
6326
|
const txt = d ? JSON.stringify(d) : "no body";
|
|
5888
6327
|
err4(`deploy '${ws}' failed (${r.status}): ${txt}`);
|
|
5889
6328
|
if (r.status === 401 || r.status === 403 || r.status === 422 || /warrant|signed|signer|unsigned|authorship|forged|relation|installDomain/i.test(txt)) {
|
|
5890
|
-
err4(` this workspace looks WARRANTED \u2014 re-run with --as <principal> to author a
|
|
6329
|
+
err4(` this workspace looks WARRANTED \u2014 re-run with --as <principal> to author a signed lifecycle offer`);
|
|
5891
6330
|
err4(` (import the admin signing key first if needed: githolon key import --principal <uid> --secret <key>)`);
|
|
5892
6331
|
}
|
|
5893
6332
|
return 1;
|
|
@@ -5895,6 +6334,7 @@ async function deploy2(ws, opts) {
|
|
|
5895
6334
|
const phase = d.installation?.[0]?.data?.["status.phase"];
|
|
5896
6335
|
phaseSuffix = phase === "Active" ? " (active)" : typeof phase === "string" ? ` (${phase.toLowerCase()})` : "";
|
|
5897
6336
|
deployedHash = typeof d.domainHash === "string" ? d.domainHash : void 0;
|
|
6337
|
+
expectsPending = d.staged === true || expectsPending;
|
|
5898
6338
|
}
|
|
5899
6339
|
const after = await fetch(`${cloud}/v2/workspaces/${ws}/domains`).then((ar) => ar.json()).then((ad) => ad.ok === true ? ad : {}).catch(() => ({}));
|
|
5900
6340
|
const currentHashes = new Set(Object.values(after.currentLaw ?? {}));
|
|
@@ -5903,13 +6343,28 @@ async function deploy2(ws, opts) {
|
|
|
5903
6343
|
const emitPlan = () => {
|
|
5904
6344
|
if (plan === void 0 || targetHash === void 0 || plan.decisions.length === 0) return;
|
|
5905
6345
|
for (const line of describeDeployPlan2(plan, targetHash)) out4(line);
|
|
5906
|
-
if (plan.replaceCandidates.length > 1) {
|
|
5907
|
-
out4(` \u26A0 the package's keys were active on ${plan.replaceCandidates.length} different installs \u2014 installDomain supersedes one (${plan.replaces.slice(0, 16)}\u2026); this deploy is active for every key.`);
|
|
5908
|
-
}
|
|
5909
|
-
if (!signed && plan.replaces !== void 0 && !opts.keepBeside) {
|
|
5910
|
-
out4(` note: the OPEN (unsigned) lane installs beside \u2014 the new law is active, and the prior install is effectively superseded but not marked Superseded. Sign with --as <uid> to record the supersession.`);
|
|
5911
|
-
}
|
|
5912
6346
|
};
|
|
6347
|
+
if (expectsPending && deployedHash !== void 0) {
|
|
6348
|
+
const row = (after.domains ?? []).find((x) => x.domainHash === deployedHash);
|
|
6349
|
+
const unchanged = Object.entries(currentLaw2).every(([key, hash]) => after.currentLaw?.[key] === hash);
|
|
6350
|
+
if (row?.phase !== "Pending" || !unchanged || isCurrent) {
|
|
6351
|
+
err4(`deploy '${ws}' refused its own outcome: a successor must be Pending while the current model keeps serving`);
|
|
6352
|
+
err4(` observed phase=${row?.phase ?? "missing"}; current law ${unchanged && !isCurrent ? "unchanged" : "changed"}`);
|
|
6353
|
+
return 2;
|
|
6354
|
+
}
|
|
6355
|
+
if (beforeDurableHead !== void 0) {
|
|
6356
|
+
const durableHead = await waitForDurableMainAdvance(cloud, ws, beforeDurableHead);
|
|
6357
|
+
if (durableHead === void 0) {
|
|
6358
|
+
err4(`deploy '${ws}' staged the candidate, but canonical Git main did not advance within 30000ms`);
|
|
6359
|
+
return 2;
|
|
6360
|
+
}
|
|
6361
|
+
}
|
|
6362
|
+
out4(`\u2713 staged ${fileName} \u2192 ${ws} (pending)`);
|
|
6363
|
+
if (plan?.supersedes) out4(` current model ${plan.supersedes.slice(0, 16)}\u2026 keeps serving`);
|
|
6364
|
+
out4(` candidate ${deployedHash.slice(0, 16)}\u2026 is in custody but cannot serve yet`);
|
|
6365
|
+
out4(` next: use the candidate generated client and call model.adopt()`);
|
|
6366
|
+
return 0;
|
|
6367
|
+
}
|
|
5913
6368
|
if (deployedHash !== void 0 && isCurrent) {
|
|
5914
6369
|
const wasCurrentBefore = Object.values(currentLaw2).includes(deployedHash);
|
|
5915
6370
|
if (!wasCurrentBefore && beforeDurableHead !== void 0) {
|
|
@@ -6316,6 +6771,39 @@ async function runOfflineLegs(eng, ws, lawHash, legs, frameworkHash, deployUsda)
|
|
|
6316
6771
|
}
|
|
6317
6772
|
return done(true, lines);
|
|
6318
6773
|
}
|
|
6774
|
+
function sealOwnedBusinessBirth(eng, payload, encryption, authorSecret, principal) {
|
|
6775
|
+
const key = payload[encryption.keyField];
|
|
6776
|
+
const digest = createHash4("sha256").update(`${encryption.namespace}${String(key)}`).digest("hex");
|
|
6777
|
+
const childWorkspace = `${encryption.namespace}-${digest.slice(0, 40)}`;
|
|
6778
|
+
const scopeKey = cryptoOwnedScopeKey(
|
|
6779
|
+
eng,
|
|
6780
|
+
childWorkspace,
|
|
6781
|
+
authorSecret,
|
|
6782
|
+
encryption.scope,
|
|
6783
|
+
principal,
|
|
6784
|
+
false
|
|
6785
|
+
);
|
|
6786
|
+
const sealed = {
|
|
6787
|
+
[OWNED_KEY_PAYLOAD_FIELD]: scopeKey.ownedKeySubject,
|
|
6788
|
+
...scopeKey.ownedCustody ? { [OWNED_CUSTODY_PAYLOAD_FIELD]: scopeKey.ownedCustody } : {}
|
|
6789
|
+
};
|
|
6790
|
+
for (const [field, slot] of Object.entries(encryption.fields)) {
|
|
6791
|
+
const value = payload[field];
|
|
6792
|
+
if (value === void 0 || value === null) continue;
|
|
6793
|
+
sealed[field] = cryptoSealField(eng, {
|
|
6794
|
+
scopeKey: scopeKey.key,
|
|
6795
|
+
scope: encryption.scope,
|
|
6796
|
+
epoch: scopeKey.epoch,
|
|
6797
|
+
aggSid: slot.aggSid,
|
|
6798
|
+
fieldSid: slot.fieldSid,
|
|
6799
|
+
plaintext: String(value)
|
|
6800
|
+
});
|
|
6801
|
+
}
|
|
6802
|
+
payload[BUSINESS_BIRTH_SEED_PAYLOAD_FIELD] = JSON.stringify(sealed);
|
|
6803
|
+
payload[OWNED_KEY_PAYLOAD_FIELD] = scopeKey.ownedKeySubject;
|
|
6804
|
+
if (scopeKey.ownedCustody) payload[OWNED_CUSTODY_PAYLOAD_FIELD] = scopeKey.ownedCustody;
|
|
6805
|
+
return { childWorkspace, scopeKey };
|
|
6806
|
+
}
|
|
6319
6807
|
function warrantParentForBirth(eng, parentWs, parentDomain, lawHash, genesisOwner, birthActor, dev2, stamp) {
|
|
6320
6808
|
const authorFrameworkAs = (directiveId, payload, actor) => {
|
|
6321
6809
|
for (const dom of [parentDomain, "nomos"]) {
|
|
@@ -6382,7 +6870,10 @@ function warrantParentForBirth(eng, parentWs, parentDomain, lawHash, genesisOwne
|
|
|
6382
6870
|
return { ok: true, attestationVerified: hasDelegation && hasParentAttestation };
|
|
6383
6871
|
}
|
|
6384
6872
|
function attestedBirthOffer(eng, parentWs, parentDomain, directiveId, payloadNoCert, lawHash, founder, dev2, verified = true) {
|
|
6385
|
-
const probe = author(eng, parentWs, parentDomain, directiveId, payloadNoCert, lawHash, {
|
|
6873
|
+
const probe = author(eng, parentWs, parentDomain, directiveId, payloadNoCert, lawHash, {
|
|
6874
|
+
actor: founder,
|
|
6875
|
+
authorSecret: dev2.secret
|
|
6876
|
+
});
|
|
6386
6877
|
if (probe.ok !== false) {
|
|
6387
6878
|
return { res: probe };
|
|
6388
6879
|
}
|
|
@@ -6489,6 +6980,7 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
|
|
|
6489
6980
|
return done(true);
|
|
6490
6981
|
}
|
|
6491
6982
|
}
|
|
6983
|
+
const ownedBirth = cb.businessEncryption !== void 0 ? sealOwnedBusinessBirth(eng, payload, cb.businessEncryption, dev2.secret, founder) : void 0;
|
|
6492
6984
|
const { res } = attestedBirthOffer(
|
|
6493
6985
|
eng,
|
|
6494
6986
|
parentWs,
|
|
@@ -6603,10 +7095,29 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
|
|
|
6603
7095
|
return done(false, `the recovered child ${childWs} FAILED verify_chain from its own custody: ${recoveredVerify.error ?? "invalid"}`);
|
|
6604
7096
|
}
|
|
6605
7097
|
if (cb.childSeedInstanceId !== void 0) {
|
|
6606
|
-
const recoveredRows = qById(
|
|
7098
|
+
const recoveredRows = qById(
|
|
7099
|
+
eng,
|
|
7100
|
+
childWs,
|
|
7101
|
+
cb.childSeedInstanceId,
|
|
7102
|
+
ownedBirth === void 0 ? "" : founder,
|
|
7103
|
+
ownedBirth === void 0 ? [] : [ownedBirth.scopeKey]
|
|
7104
|
+
);
|
|
6607
7105
|
if (recoveredRows.length < 1) {
|
|
6608
7106
|
return done(false, `the recovered child ${childWs} verified but its business root ${cb.childSeedInstanceId} was missing`);
|
|
6609
7107
|
}
|
|
7108
|
+
if (ownedBirth !== void 0 && cb.businessEncryption !== void 0) {
|
|
7109
|
+
if (childWs !== ownedBirth.childWorkspace) {
|
|
7110
|
+
return done(false, `the born child '${childWs}' differs from the deterministic owned-custody address '${ownedBirth.childWorkspace}'`);
|
|
7111
|
+
}
|
|
7112
|
+
const data = recoveredRows[0]?.data ?? {};
|
|
7113
|
+
for (const field of Object.keys(cb.businessEncryption.fields)) {
|
|
7114
|
+
const expected = cb.birthPayload[field];
|
|
7115
|
+
if (expected !== void 0 && data[field] !== expected) {
|
|
7116
|
+
return done(false, `the recovered owned ${cb.businessAggregateId ?? "aggregate"} did not decrypt '${field}' back to its business fact`);
|
|
7117
|
+
}
|
|
7118
|
+
}
|
|
7119
|
+
lines.push(`\u2713 owned custody \u2014 recovered business facts decrypted under the creator's framework-managed device key`);
|
|
7120
|
+
}
|
|
6610
7121
|
}
|
|
6611
7122
|
if (cb.businessAggregateId !== void 0) {
|
|
6612
7123
|
lines.push(`\u2713 persistence + recovery \u2014 evicted, restored from durable custody, and ${cb.businessAggregateId} read back`);
|
|
@@ -6870,7 +7381,7 @@ OFFLINE PROOF GREEN (${Math.round(v.ms)}ms) \u2014 the same legs rerun on every
|
|
|
6870
7381
|
console.log(`Run the same generated business proof against Nomos Cloud when ready: githolon proof --live`);
|
|
6871
7382
|
return 0;
|
|
6872
7383
|
}
|
|
6873
|
-
var keyHashOf, OFFLINE_PROOF_VERIFIER;
|
|
7384
|
+
var keyHashOf, OFFLINE_PROOF_VERIFIER, OWNED_KEY_PAYLOAD_FIELD, OWNED_CUSTODY_PAYLOAD_FIELD, BUSINESS_BIRTH_SEED_PAYLOAD_FIELD;
|
|
6874
7385
|
var init_proof_offline = __esm({
|
|
6875
7386
|
"src/proof_offline.ts"() {
|
|
6876
7387
|
"use strict";
|
|
@@ -6878,6 +7389,9 @@ var init_proof_offline = __esm({
|
|
|
6878
7389
|
init_local_holon();
|
|
6879
7390
|
keyHashOf = (pubB64) => createHash4("sha256").update(Buffer.from(pubB64, "base64")).digest("hex");
|
|
6880
7391
|
OFFLINE_PROOF_VERIFIER = "nomos:test-mint";
|
|
7392
|
+
OWNED_KEY_PAYLOAD_FIELD = "__nomos_owned_device_key_subject_7c1f5e";
|
|
7393
|
+
OWNED_CUSTODY_PAYLOAD_FIELD = "__nomos_owned_device_custody_7c1f5e";
|
|
7394
|
+
BUSINESS_BIRTH_SEED_PAYLOAD_FIELD = "__nomos_birth_seed_payload_7c1f5e";
|
|
6881
7395
|
}
|
|
6882
7396
|
});
|
|
6883
7397
|
|
|
@@ -8694,7 +9208,7 @@ export const ${n.pascal} = aggregate("${n.pascal}", {
|
|
|
8694
9208
|
status: t.enum(${n.statusesConst}).merge(Lww),
|
|
8695
9209
|
tags: t.set(t.string()).merge(AddWins),
|
|
8696
9210
|
customFields: t.map(t.string()).merge(MapOf(Lww)),
|
|
8697
|
-
});`;
|
|
9211
|
+
}).public();`;
|
|
8698
9212
|
}
|
|
8699
9213
|
function domainTemplate(raw) {
|
|
8700
9214
|
const n = namesFor(raw);
|
|
@@ -8766,7 +9280,7 @@ import { z, aggregate, directive, t, Conflict, set } from "@githolon/dsl";
|
|
|
8766
9280
|
// Stub target \u2014 in a real domain, import the existing aggregate handle instead.
|
|
8767
9281
|
export const ${n.pascal} = aggregate("${n.pascal}", {
|
|
8768
9282
|
label: t.string().merge(Conflict),
|
|
8769
|
-
});
|
|
9283
|
+
}).public();
|
|
8770
9284
|
|
|
8771
9285
|
/** ${n.camel} \u2014 .mutates the target aggregate. */
|
|
8772
9286
|
export const ${n.camel} = directive("${n.camel}")
|
|
@@ -9481,21 +9995,19 @@ var HELP = {
|
|
|
9481
9995
|
examples: ["githolon revoke creation 32c7100e-\u2026", "githolon revoke admin 32c7100e-\u2026"]
|
|
9482
9996
|
},
|
|
9483
9997
|
deploy: {
|
|
9484
|
-
usage: "githolon deploy [<ws>] [--as <uid>] [--
|
|
9485
|
-
what: "
|
|
9998
|
+
usage: "githolon deploy [<ws>] [--as <uid>] [--file <deploy.json>] [--cloud <url>] [--target <name>]",
|
|
9999
|
+
what: "Put the compiled model in the workspace's verified custody. There is one lifecycle: the first\nmodel becomes active so a blank application can start; every successor stays Pending while the current\nmodel keeps serving. The candidate generated client then runs the exact-history proof through\n`model.adopt()` and either adopts immediately or returns a business-readable decision requiring\n`decision.accept(reason)`. Deployment cannot choose a replacement mode or bypass that proof.\nRe-deploying the same content hash is idempotent. With no <ws>, the project's workspace binding resolves it.",
|
|
9486
10000
|
flags: [
|
|
9487
|
-
["--as <uid>", "
|
|
9488
|
-
["--keep-beside", "install beside the prior law (the old multi-version default; prior becomes effectively superseded by recency)"],
|
|
9489
|
-
["--retire-replaced", "supersede via Retired \u2014 the prior install is explicitly withdrawn"],
|
|
10001
|
+
["--as <uid>", "attribute the deployment to this principal (needs its enrolled signing key)"],
|
|
9490
10002
|
["--file <path>", "an explicit deploy body (default: the one build/*.deploy.json)"],
|
|
9491
10003
|
["--target <name>", "pick among named targets (workspace: { dev: \u2026, prod: \u2026 })"],
|
|
9492
10004
|
["--cloud <url>", "target cloud"]
|
|
9493
10005
|
],
|
|
9494
|
-
examples: ["githolon deploy", "githolon deploy my-guestbook", "githolon deploy co2-platform --as <admin-uid>"
|
|
10006
|
+
examples: ["githolon deploy", "githolon deploy my-guestbook", "githolon deploy co2-platform --as <admin-uid>"]
|
|
9495
10007
|
},
|
|
9496
10008
|
domains: {
|
|
9497
10009
|
usage: "githolon domains <status <ws> [--explain-current-interface] | retire <ws> <hashOrKey> [--with <hashOrKey>]>",
|
|
9498
|
-
what: "
|
|
10010
|
+
what: "Framework lifecycle inspection and explicit withdrawal.\n\u2022 status: per domain KEY, the active hash, then the superseded/retired lineage behind it.\n Lifecycle vocabulary: active = served now; superseded = replaced by a newer install for the same domain\n key, replayable, not served; retired = explicitly withdrawn, replayable, not served.\n --explain-current-interface spells out why active reads/dispatch use only that active map.\n\u2022 retire: mark an install Retired via a signed installDomain offer. The framework retires only as the\n consequence of installing a SUCCESSOR \u2014 by default the local compiled package (build/*.deploy.json),\n or --with <hashOrKey> names an already-installed successor. A key the successor does not cover is left\n with NO active law \u2014 WARNED loudly, never blocked. A key resolves to its active hash; a 64-hex arg is\n taken as the install hash.",
|
|
9499
10011
|
flags: [
|
|
9500
10012
|
["--explain-current-interface", "status: also explain the frontier resolution (why the interface is what it is)"],
|
|
9501
10013
|
["--with <hashOrKey>", "retire: the retiring successor package \u2014 an already-installed hash or served key"],
|
|
@@ -9506,7 +10018,7 @@ var HELP = {
|
|
|
9506
10018
|
},
|
|
9507
10019
|
secret: {
|
|
9508
10020
|
usage: "githolon secret <set <ws> <push-password> | rotate <ws>> [--cloud <url>]",
|
|
9509
|
-
what: "The git push-password store (~/.holon/credentials.json, 0600) for authenticated git sync to the\ncloud host.
|
|
10021
|
+
what: "The git push-password store (~/.holon/credentials.json, 0600) for authenticated git sync to the\ncloud host. Deployment has no host secret. `set` imports a push password you already hold;\n`rotate` is RETIRED (the host holds no ownership credential to rotate \u2014 410). (There is no\npush-to-create birth: a workspace is born by its parent authoring its birth.)",
|
|
9510
10022
|
examples: ["githolon secret set my-ws holon_v1_\u2026"]
|
|
9511
10023
|
},
|
|
9512
10024
|
git: {
|
|
@@ -10052,15 +10564,13 @@ function cloudArgs(rest) {
|
|
|
10052
10564
|
const pos = [];
|
|
10053
10565
|
const opts = {};
|
|
10054
10566
|
const VALUE_FLAGS = ["--cloud", "--principal", "--as", "--file", "--target", "--parent", "--via", "--max", "--label", "--secret", "--payload", "--payload-file", "--save", "--format", "--with", "--out", "--reason", "--oid", "--seed-secret", "--gcp-secret", "--controller-hash", "--plan", "--depth", "--domain", "--directive"];
|
|
10055
|
-
const BOOL_FLAGS = ["--sha256", "--stamp", "--yes", "--clear", "--
|
|
10567
|
+
const BOOL_FLAGS = ["--sha256", "--stamp", "--yes", "--clear", "--explain-current-interface", "--dry-run", "--json", "--full"];
|
|
10056
10568
|
for (let i = 0; i < rest.length; i++) {
|
|
10057
10569
|
const a = rest[i];
|
|
10058
10570
|
if (BOOL_FLAGS.includes(a)) {
|
|
10059
10571
|
if (a === "--sha256") opts.sha256 = true;
|
|
10060
10572
|
else if (a === "--stamp") opts.stamp = true;
|
|
10061
10573
|
else if (a === "--clear") opts.clear = true;
|
|
10062
|
-
else if (a === "--keep-beside") opts.keepBeside = true;
|
|
10063
|
-
else if (a === "--retire-replaced") opts.retireReplaced = true;
|
|
10064
10574
|
else if (a === "--explain-current-interface") opts.explain = true;
|
|
10065
10575
|
else if (a === "--dry-run") opts.dryRun = true;
|
|
10066
10576
|
else if (a === "--json") opts.json = true;
|