githolon 0.23.1 → 0.24.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 +70 -17
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -20,7 +20,8 @@ __export(governance_exports, {
|
|
|
20
20
|
keyImport: () => keyImport,
|
|
21
21
|
keyShow: () => keyShow,
|
|
22
22
|
resolveGovernancePrincipal: () => resolveGovernancePrincipal,
|
|
23
|
-
signAndPostGovernance: () => signAndPostGovernance
|
|
23
|
+
signAndPostGovernance: () => signAndPostGovernance,
|
|
24
|
+
signAndPostOffer: () => signAndPostOffer
|
|
24
25
|
});
|
|
25
26
|
import { createHash, createPrivateKey, createPublicKey } from "node:crypto";
|
|
26
27
|
import { readFileSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
@@ -56,20 +57,24 @@ function resolveGovernancePrincipal(opts) {
|
|
|
56
57
|
}
|
|
57
58
|
return principal;
|
|
58
59
|
}
|
|
59
|
-
async function
|
|
60
|
+
async function signAndPostOffer(ws, domain, directiveId, payload, opts) {
|
|
60
61
|
const cloud = cloudBase(opts.cloud);
|
|
61
62
|
const principal = resolveGovernancePrincipal(opts);
|
|
62
|
-
const holon = await connectGovernance(cloud,
|
|
63
|
+
const holon = await connectGovernance(cloud, ws);
|
|
63
64
|
const device = await ensureDeviceKey(holon, principal);
|
|
64
65
|
const sealed = await holon.signGovernanceOffer({
|
|
66
|
+
domain,
|
|
65
67
|
directiveId,
|
|
66
68
|
payload,
|
|
67
69
|
authorSecret: device.secret,
|
|
68
70
|
actor: `user:${principal}`
|
|
69
71
|
});
|
|
70
|
-
const verdict = await holon.postGovernanceOffer({ directiveId, intentBytes: sealed.intentBytes, ws
|
|
72
|
+
const verdict = await holon.postGovernanceOffer({ directiveId, intentBytes: sealed.intentBytes, ws });
|
|
71
73
|
return { ...verdict, principal };
|
|
72
74
|
}
|
|
75
|
+
async function signAndPostGovernance(parent, directiveId, payload, opts) {
|
|
76
|
+
return signAndPostOffer(parent, "workspaces", directiveId, payload, opts);
|
|
77
|
+
}
|
|
73
78
|
async function grantOrRevoke(verb, kind, subject, opts) {
|
|
74
79
|
const parent = opts.parent ?? "root";
|
|
75
80
|
const now = Date.now();
|
|
@@ -367,6 +372,7 @@ __export(cloud_exports, {
|
|
|
367
372
|
wsStatus: () => wsStatus
|
|
368
373
|
});
|
|
369
374
|
import { chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
375
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
370
376
|
import { join as join2 } from "node:path";
|
|
371
377
|
import { homedir } from "node:os";
|
|
372
378
|
function cloudBase(flag) {
|
|
@@ -645,21 +651,68 @@ async function deploy(ws, opts) {
|
|
|
645
651
|
err2(e.message);
|
|
646
652
|
return 1;
|
|
647
653
|
}
|
|
654
|
+
const fileName = file.split("/").pop();
|
|
648
655
|
const before = await fetch(`${cloud}/v2/workspaces/${ws}/domains`).then((br) => br.json()).then((bd) => bd.ok === true ? bd.domains ?? [] : []).catch(() => []);
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
656
|
+
const principal = opts.principal ?? currentPrincipal();
|
|
657
|
+
const signed = opts.principal !== void 0 || principal !== void 0 && getDeviceKey(principal) !== void 0;
|
|
658
|
+
let phaseSuffix = "";
|
|
659
|
+
let deployedHash;
|
|
660
|
+
if (signed) {
|
|
661
|
+
let body;
|
|
662
|
+
try {
|
|
663
|
+
body = JSON.parse(readFileSync2(file, "utf8"));
|
|
664
|
+
} catch (e) {
|
|
665
|
+
err2(`deploy body ${file} is not valid JSON \u2014 recompile: ${e.message}`);
|
|
666
|
+
return 1;
|
|
667
|
+
}
|
|
668
|
+
const packageUsda = body.packageUsda;
|
|
669
|
+
if (typeof packageUsda !== "string" || packageUsda === "") {
|
|
670
|
+
err2(`deploy body ${file} is missing packageUsda \u2014 run \`githolon compile\` again`);
|
|
671
|
+
return 1;
|
|
672
|
+
}
|
|
673
|
+
const targetHash = createHash2("sha256").update(Buffer.from(packageUsda, "utf8")).digest("hex");
|
|
674
|
+
const { signAndPostOffer: signAndPostOffer2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
675
|
+
let v;
|
|
676
|
+
try {
|
|
677
|
+
const who = resolveGovernancePrincipal2(opts);
|
|
678
|
+
const installPayload2 = {
|
|
679
|
+
domainHash: targetHash,
|
|
680
|
+
packageUsda,
|
|
681
|
+
installedBy: `user:${who}`,
|
|
682
|
+
dependencies: [],
|
|
683
|
+
finalizers: [],
|
|
684
|
+
...body.dispositions !== void 0 && body.dispositions !== null ? { dispositions: body.dispositions } : {}
|
|
685
|
+
};
|
|
686
|
+
v = await signAndPostOffer2(ws, "nomos", "installDomain", installPayload2, opts);
|
|
687
|
+
} catch (e) {
|
|
688
|
+
err2(e.message);
|
|
689
|
+
return 1;
|
|
690
|
+
}
|
|
691
|
+
if (!v.ok) {
|
|
692
|
+
err2(`signed deploy '${ws}' refused (${v.status}): ${typeof v.body === "string" ? v.body : JSON.stringify(v.body)}`);
|
|
693
|
+
return 1;
|
|
694
|
+
}
|
|
695
|
+
deployedHash = targetHash;
|
|
696
|
+
} else {
|
|
697
|
+
const r = await fetch(`${cloud}/v2/workspaces/${ws}/domains`, {
|
|
698
|
+
method: "POST",
|
|
699
|
+
headers: { "content-type": "application/json" },
|
|
700
|
+
body: readFileSync2(file, "utf8")
|
|
701
|
+
});
|
|
702
|
+
const d = await r.json().catch(() => void 0);
|
|
703
|
+
if (!r.ok || d?.ok !== true) {
|
|
704
|
+
const txt = d ? JSON.stringify(d) : "no body";
|
|
705
|
+
err2(`deploy '${ws}' failed (${r.status}): ${txt}`);
|
|
706
|
+
if (r.status === 401 || r.status === 403 || r.status === 422 || /warrant|signed|signer|unsigned|authorship|forged|relation|installDomain/i.test(txt)) {
|
|
707
|
+
err2(` this workspace looks WARRANTED \u2014 re-run with --as <principal> to author a SIGNED install offer`);
|
|
708
|
+
err2(` (import the admin signing key first if needed: githolon key import --principal <uid> --secret <key>)`);
|
|
709
|
+
}
|
|
710
|
+
return 1;
|
|
711
|
+
}
|
|
712
|
+
const phase = d.installation?.[0]?.data?.["status.phase"];
|
|
713
|
+
phaseSuffix = typeof phase === "string" ? ` (${phase})` : "";
|
|
714
|
+
deployedHash = typeof d.domainHash === "string" ? d.domainHash : void 0;
|
|
658
715
|
}
|
|
659
|
-
const phase = d.installation?.[0]?.data?.["status.phase"];
|
|
660
|
-
const fileName = file.split("/").pop();
|
|
661
|
-
const phaseSuffix = typeof phase === "string" ? ` (${phase})` : "";
|
|
662
|
-
const deployedHash = typeof d.domainHash === "string" ? d.domainHash : void 0;
|
|
663
716
|
const after = await fetch(`${cloud}/v2/workspaces/${ws}/domains`).then((ar) => ar.json()).then((ad) => ad.ok === true ? ad : {}).catch(() => ({}));
|
|
664
717
|
const currentHashes = new Set(Object.values(after.currentLaw ?? {}));
|
|
665
718
|
const hasCurrencyData = Object.keys(after.currentLaw ?? {}).length > 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "githolon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.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",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@bjorn3/browser_wasi_shim": "0.4.2",
|
|
30
|
-
"@githolon/client": "^0.
|
|
31
|
-
"@githolon/dsl": "^0.
|
|
30
|
+
"@githolon/client": "^0.24.0",
|
|
31
|
+
"@githolon/dsl": "^0.24.0",
|
|
32
32
|
"isomorphic-git": "^1.38.4"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|