githolon 0.24.1 → 0.25.0
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 +89 -17
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -53,7 +53,7 @@ async function ensureDeviceKey(holon, principal) {
|
|
|
53
53
|
return key;
|
|
54
54
|
}
|
|
55
55
|
function resolveGovernancePrincipal(opts) {
|
|
56
|
-
const principal = opts.principal ??
|
|
56
|
+
const principal = opts.principal ?? activePrincipal();
|
|
57
57
|
if (principal === void 0) {
|
|
58
58
|
throw new Error(
|
|
59
59
|
"signed governance needs a principal \u2014 githolon login --agent (self-onboarding), or pass --principal <your-auth-uid>"
|
|
@@ -124,7 +124,7 @@ async function grantOrRevoke(verb, kind, subject, opts) {
|
|
|
124
124
|
}
|
|
125
125
|
async function keyEnroll(opts) {
|
|
126
126
|
const cloud = cloudBase(opts.cloud);
|
|
127
|
-
const principal = opts.principal ??
|
|
127
|
+
const principal = opts.principal ?? activePrincipal();
|
|
128
128
|
if (principal === void 0) {
|
|
129
129
|
err("enroll needs a principal \u2014 githolon login --agent first (or --principal <uid>)");
|
|
130
130
|
return 1;
|
|
@@ -155,7 +155,7 @@ async function keyEnroll(opts) {
|
|
|
155
155
|
return 0;
|
|
156
156
|
}
|
|
157
157
|
async function keyShow(opts) {
|
|
158
|
-
const principal = opts.principal ??
|
|
158
|
+
const principal = opts.principal ?? activePrincipal();
|
|
159
159
|
if (principal === void 0) {
|
|
160
160
|
out("no principal on file \u2014 githolon login --agent, or pass --principal <uid>");
|
|
161
161
|
return 0;
|
|
@@ -192,7 +192,7 @@ function seedFromInput(input, opts) {
|
|
|
192
192
|
);
|
|
193
193
|
}
|
|
194
194
|
async function keyImport(opts) {
|
|
195
|
-
const principal = opts.principal ??
|
|
195
|
+
const principal = opts.principal ?? activePrincipal();
|
|
196
196
|
if (principal === void 0) {
|
|
197
197
|
err("key import needs --principal <uid> (the auth-uid this key authors as)");
|
|
198
198
|
return 1;
|
|
@@ -221,7 +221,7 @@ async function keyImport(opts) {
|
|
|
221
221
|
return 0;
|
|
222
222
|
}
|
|
223
223
|
async function keyExport(opts) {
|
|
224
|
-
const principal = opts.principal ??
|
|
224
|
+
const principal = opts.principal ?? activePrincipal();
|
|
225
225
|
if (principal === void 0) {
|
|
226
226
|
err("key export needs --principal <uid>");
|
|
227
227
|
return 1;
|
|
@@ -351,6 +351,9 @@ var init_governance = __esm({
|
|
|
351
351
|
// src/cloud.ts
|
|
352
352
|
var cloud_exports = {};
|
|
353
353
|
__export(cloud_exports, {
|
|
354
|
+
activePrincipal: () => activePrincipal,
|
|
355
|
+
authUse: () => authUse,
|
|
356
|
+
clearActAs: () => clearActAs,
|
|
354
357
|
cloudBase: () => cloudBase,
|
|
355
358
|
configDir: () => configDir,
|
|
356
359
|
currentPrincipal: () => currentPrincipal,
|
|
@@ -366,6 +369,7 @@ __export(cloud_exports, {
|
|
|
366
369
|
secretRotate: () => secretRotate,
|
|
367
370
|
secretSet: () => secretSet,
|
|
368
371
|
sessionToken: () => sessionToken,
|
|
372
|
+
setActAs: () => setActAs,
|
|
369
373
|
setDeviceKey: () => setDeviceKey,
|
|
370
374
|
setPrincipal: () => setPrincipal,
|
|
371
375
|
setSecret: () => setSecret,
|
|
@@ -420,6 +424,43 @@ function currentPrincipal() {
|
|
|
420
424
|
const c = loadCreds();
|
|
421
425
|
return c.session?.uid ?? c.principal;
|
|
422
426
|
}
|
|
427
|
+
function activePrincipal() {
|
|
428
|
+
return loadCreds().actAs ?? currentPrincipal();
|
|
429
|
+
}
|
|
430
|
+
function setActAs(principal) {
|
|
431
|
+
const c = loadCreds();
|
|
432
|
+
c.actAs = principal;
|
|
433
|
+
saveCreds(c);
|
|
434
|
+
}
|
|
435
|
+
function clearActAs() {
|
|
436
|
+
const c = loadCreds();
|
|
437
|
+
delete c.actAs;
|
|
438
|
+
saveCreds(c);
|
|
439
|
+
}
|
|
440
|
+
async function authUse(principal, opts = {}) {
|
|
441
|
+
if (opts.clear === true) {
|
|
442
|
+
clearActAs();
|
|
443
|
+
out2("\u2713 cleared the active signing principal \u2014 signed lanes fall back to the session / bare default");
|
|
444
|
+
return 0;
|
|
445
|
+
}
|
|
446
|
+
if (principal === void 0) {
|
|
447
|
+
const c = loadCreds();
|
|
448
|
+
const active = c.actAs;
|
|
449
|
+
out2(active !== void 0 ? `acting as ${active}${getDeviceKey(active) ? " (key on file \u2713)" : " \u26A0 no signing key \u2014 githolon key import --principal " + active}` : "no active signing principal set (githolon use <uid>) \u2014 signed lanes use the session / bare default");
|
|
450
|
+
const keyed = Object.keys(c.devices ?? {});
|
|
451
|
+
if (keyed.length > 0) {
|
|
452
|
+
out2(`keys on file:`);
|
|
453
|
+
for (const p of keyed) out2(` ${p}${p === active ? " \u2190 active" : ""}`);
|
|
454
|
+
}
|
|
455
|
+
return 0;
|
|
456
|
+
}
|
|
457
|
+
setActAs(principal);
|
|
458
|
+
out2(`\u2713 now acting as ${principal} (signed deploy/gov/grant/key author as this principal)`);
|
|
459
|
+
if (getDeviceKey(principal) === void 0) {
|
|
460
|
+
out2(` \u26A0 no signing key on file for ${principal} yet \u2014 import it: githolon key import --principal ${principal} --secret <key>`);
|
|
461
|
+
}
|
|
462
|
+
return 0;
|
|
463
|
+
}
|
|
423
464
|
function getDeviceKey(principal) {
|
|
424
465
|
return loadCreds().devices?.[principal];
|
|
425
466
|
}
|
|
@@ -510,13 +551,21 @@ async function whoami() {
|
|
|
510
551
|
const c = loadCreds();
|
|
511
552
|
if (c.session !== void 0) {
|
|
512
553
|
out2(`session: ${c.session.anonymous ? "anonymous agent" : "account"} uid ${c.session.uid} (auth ${c.session.url})`);
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
if (c.principal !== void 0) {
|
|
554
|
+
} else if (c.principal !== void 0) {
|
|
516
555
|
out2(`bare principal (transitional, unverified): ${c.principal}`);
|
|
517
|
-
|
|
556
|
+
} else {
|
|
557
|
+
out2("not logged in \u2014 githolon login --agent, or pass --principal <uid> per birth");
|
|
558
|
+
}
|
|
559
|
+
const active = activePrincipal();
|
|
560
|
+
if (c.actAs !== void 0) {
|
|
561
|
+
out2(`acting as: ${c.actAs}${getDeviceKey(c.actAs) ? " (key on file \u2713)" : " \u26A0 no signing key"} [githolon use <uid> to switch]`);
|
|
562
|
+
} else if (active !== void 0) {
|
|
563
|
+
out2(`signed lanes act as: ${active} (the session/bare default \u2014 githolon use <uid> to switch)`);
|
|
564
|
+
}
|
|
565
|
+
const keyed = Object.keys(c.devices ?? {});
|
|
566
|
+
if (keyed.length > 0) {
|
|
567
|
+
out2(`signing keys on file: ${keyed.map((p) => p === active ? `${p} \u2190active` : p).join(", ")}`);
|
|
518
568
|
}
|
|
519
|
-
out2("not logged in \u2014 githolon login --agent, or pass --principal <uid> per birth");
|
|
520
569
|
return 0;
|
|
521
570
|
}
|
|
522
571
|
async function logout() {
|
|
@@ -657,7 +706,7 @@ async function deploy(ws, opts) {
|
|
|
657
706
|
}
|
|
658
707
|
const fileName = file.split("/").pop();
|
|
659
708
|
const before = await fetch(`${cloud}/v2/workspaces/${ws}/domains`).then((br) => br.json()).then((bd) => bd.ok === true ? bd.domains ?? [] : []).catch(() => []);
|
|
660
|
-
const principal = opts.principal ??
|
|
709
|
+
const principal = opts.principal ?? activePrincipal();
|
|
661
710
|
const signed = opts.principal !== void 0 || principal !== void 0 && getDeviceKey(principal) !== void 0;
|
|
662
711
|
let phaseSuffix = "";
|
|
663
712
|
let deployedHash;
|
|
@@ -2418,7 +2467,16 @@ var HELP = {
|
|
|
2418
2467
|
},
|
|
2419
2468
|
whoami: {
|
|
2420
2469
|
usage: "githolon whoami",
|
|
2421
|
-
what: "Show the principal births will ride (session uid, or the transitional bare uid)."
|
|
2470
|
+
what: "Show the principal births will ride (session uid, or the transitional bare uid), the ACTIVE\nsigning principal (githolon use), and the signing keys on file."
|
|
2471
|
+
},
|
|
2472
|
+
use: {
|
|
2473
|
+
usage: "githolon use [<uid>] [--clear]",
|
|
2474
|
+
what: "Set, show, or clear the ACTIVE signing principal \u2014 the one the signed lanes (deploy, gov, grant,\nkey) author as by DEFAULT, without an explicit --as. Pair with `githolon key import` to hold an\nenrolled key per principal (a platform admin key, your own uid, \u2026) and switch which one acts with\none command. `--as`/`--principal` still overrides per-command. No argument shows the active\nprincipal + keys on file; `--clear` falls back to the session/bare default. Stored in ~/.holon.",
|
|
2475
|
+
flags: [
|
|
2476
|
+
["<uid>", "the auth-uid to act as (must have a signing key \u2014 githolon key import)"],
|
|
2477
|
+
["--clear", "clear the active principal (signed lanes use the session/bare default)"]
|
|
2478
|
+
],
|
|
2479
|
+
examples: ["githolon use d205ca94-...", "githolon use", "githolon use --clear"]
|
|
2422
2480
|
},
|
|
2423
2481
|
logout: {
|
|
2424
2482
|
usage: "githolon logout",
|
|
@@ -2494,14 +2552,15 @@ var HELP = {
|
|
|
2494
2552
|
examples: ["githolon revoke creation 32c7100e-\u2026", "githolon revoke admin 32c7100e-\u2026"]
|
|
2495
2553
|
},
|
|
2496
2554
|
deploy: {
|
|
2497
|
-
usage: "githolon deploy [<ws>] [--file <deploy.json>] [--cloud <url>] [--target <name>]",
|
|
2498
|
-
what: "
|
|
2555
|
+
usage: "githolon deploy [<ws>] [--as <uid>] [--file <deploy.json>] [--cloud <url>] [--target <name>]",
|
|
2556
|
+
what: "Deploy build/*.deploy.json \u2014 kernel-gated, no host secret. TWO lanes, picked automatically:\n\u2022 SIGNED (a WARRANTED ws, or when --as / the active `githolon use` principal has a signing key on\n file): signs a `nomos/installDomain` offer with that key and relays it; the kernel re-verifies the\n signature + judges the installDomain relation. Required for warranted platforms (co2, tbx) \u2014 an\n unsigned install is refused there.\n\u2022 OPEN (unwarranted ws / no key): the open POST /domains, still kernel-judged.\nAfter the POST it re-reads the workspace and CONFIRMS the deployed hash is the CURRENT serving law\n(exit 2 if committed-but-not-current). Prints what MOVED (old \u2192 new law hash). With no <ws>, the\nproject's `workspace` binding in nomos.package.mjs resolves it.",
|
|
2499
2557
|
flags: [
|
|
2558
|
+
["--as <uid>", "deploy as this principal via the SIGNED lane (needs its key \u2014 githolon key import; else githolon use)"],
|
|
2500
2559
|
["--file <path>", "an explicit deploy body (default: the one build/*.deploy.json)"],
|
|
2501
2560
|
["--target <name>", "pick among named targets (workspace: { dev: \u2026, prod: \u2026 })"],
|
|
2502
2561
|
["--cloud <url>", "target cloud"]
|
|
2503
2562
|
],
|
|
2504
|
-
examples: ["githolon deploy", "githolon deploy my-guestbook", "githolon deploy --
|
|
2563
|
+
examples: ["githolon deploy", "githolon deploy my-guestbook", "githolon use <admin-uid> && githolon deploy co2-platform", "githolon deploy tbx --as <admin-uid>"]
|
|
2505
2564
|
},
|
|
2506
2565
|
secret: {
|
|
2507
2566
|
usage: "githolon secret <set <ws> <push-password> | rotate <ws>> [--cloud <url>]",
|
|
@@ -2988,7 +3047,9 @@ Authoring:
|
|
|
2988
3047
|
Identity (~/.holon/credentials.json \u2014 sessions auto-refresh):
|
|
2989
3048
|
githolon login --agent anonymous sign-in: a verified self-onboarded identity
|
|
2990
3049
|
githolon login --token <refresh_token> adopt an existing captain app session
|
|
2991
|
-
githolon whoami show the principal births will ride
|
|
3050
|
+
githolon whoami show the principal births will ride + keys on file
|
|
3051
|
+
githolon use [<uid>] [--clear] set/show/clear the ACTIVE signing principal: the one
|
|
3052
|
+
deploy/gov/grant/key author as (--as overrides per-cmd)
|
|
2992
3053
|
githolon logout clear the session (workspace secrets kept)
|
|
2993
3054
|
githolon key enroll [--principal <uid>] [--parent <ws>] mint a signing device key + enroll it on-chain
|
|
2994
3055
|
(secret stays local; warrants SIGNED governance)
|
|
@@ -3044,12 +3105,13 @@ function cloudArgs(rest) {
|
|
|
3044
3105
|
const pos = [];
|
|
3045
3106
|
const opts = {};
|
|
3046
3107
|
const VALUE_FLAGS = ["--cloud", "--principal", "--as", "--file", "--target", "--parent", "--via", "--max", "--label", "--secret", "--payload", "--payload-file", "--save", "--format"];
|
|
3047
|
-
const BOOL_FLAGS = ["--sha256", "--stamp", "--yes"];
|
|
3108
|
+
const BOOL_FLAGS = ["--sha256", "--stamp", "--yes", "--clear"];
|
|
3048
3109
|
for (let i = 0; i < rest.length; i++) {
|
|
3049
3110
|
const a = rest[i];
|
|
3050
3111
|
if (BOOL_FLAGS.includes(a)) {
|
|
3051
3112
|
if (a === "--sha256") opts.sha256 = true;
|
|
3052
3113
|
else if (a === "--stamp") opts.stamp = true;
|
|
3114
|
+
else if (a === "--clear") opts.clear = true;
|
|
3053
3115
|
else opts.yes = true;
|
|
3054
3116
|
} else if (VALUE_FLAGS.includes(a)) {
|
|
3055
3117
|
const v = rest[++i];
|
|
@@ -3453,6 +3515,16 @@ ${USAGE}`);
|
|
|
3453
3515
|
}
|
|
3454
3516
|
if (argv[0] === "whoami") return whoami();
|
|
3455
3517
|
if (argv[0] === "logout") return logout();
|
|
3518
|
+
if (argv[0] === "use") {
|
|
3519
|
+
const { pos, opts, bad } = cloudArgs(argv.slice(1));
|
|
3520
|
+
if (bad !== void 0) {
|
|
3521
|
+
process.stderr.write(`error: ${bad}
|
|
3522
|
+
|
|
3523
|
+
${USAGE}`);
|
|
3524
|
+
return 1;
|
|
3525
|
+
}
|
|
3526
|
+
return authUse(pos[0], { clear: opts.clear === true });
|
|
3527
|
+
}
|
|
3456
3528
|
if (argv[0] === "ledger") {
|
|
3457
3529
|
const { pos, opts, bad } = cloudArgs(argv.slice(1));
|
|
3458
3530
|
if (bad !== void 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "githolon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "githolon — the Nomos developer CLI: Rails-style generators for @githolon/dsl domains + the package compiler. Kernel-independent.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@bjorn3/browser_wasi_shim": "0.4.2",
|
|
32
|
-
"@githolon/client": "^0.
|
|
33
|
-
"@githolon/dsl": "^0.
|
|
32
|
+
"@githolon/client": "^0.25.0",
|
|
33
|
+
"@githolon/dsl": "^0.25.0",
|
|
34
34
|
"isomorphic-git": "^1.38.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|