githolon 0.34.0 → 0.34.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.
Files changed (2) hide show
  1. package/dist/cli.mjs +79 -9
  2. package/package.json +3 -3
package/dist/cli.mjs CHANGED
@@ -924,20 +924,45 @@ async function wsRetire(ws, opts) {
924
924
  const cloud = cloudBase(opts.cloud);
925
925
  const { signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
926
926
  const parent = opts.parent ?? "root";
927
+ let record;
928
+ try {
929
+ const q = await fetch(`${cloud}/v2/workspaces/${parent}/workspaceByName?name=${encodeURIComponent(ws)}`);
930
+ const qd = await q.json().catch(() => void 0);
931
+ const rows = qd?.ok === true ? qd.rows ?? [] : [];
932
+ record = rows.find((r) => r.data?.status !== "retired" && r.data?.status !== "reclaimed") ?? rows[0];
933
+ } catch {
934
+ }
935
+ const recordId = record?.id;
936
+ if (recordId === void 0) {
937
+ err3(
938
+ `retire '${ws}': no CloudWorkspace record named '${ws}' in ${parent}'s registry \u2014 nothing lawful to retire.
939
+ (a workspace born via the OPEN lane \u2014 bare POST /v2/workspaces/${ws} \u2014 has no registry row;
940
+ registered births ride \`githolon ws create ${ws} --via ${parent}\`. An unregistered leak needs a custodian sweep.)`
941
+ );
942
+ return 1;
943
+ }
927
944
  let v;
928
945
  try {
929
946
  const principal = resolveGovernancePrincipal2(opts);
930
- const payload = { workspaceId: ws, retiredBy: principal, retiredAt: Date.now() };
931
- v = await signAndPostGovernance2(parent, "retireOwnWorkspace", payload, opts);
932
- if (!v.ok && v.status === 422) {
933
- v = await signAndPostGovernance2(parent, "retireWorkspace", payload, opts);
934
- }
947
+ const payload = { workspaceId: recordId, retiredBy: principal, retiredAt: Date.now() };
948
+ const bare = (s) => s.startsWith("user:") ? s.slice(5) : s;
949
+ const creator = record?.data?.createdBy ?? record?.data?.principal ?? "";
950
+ const own = creator !== "" && bare(creator) === bare(principal);
951
+ v = await signAndPostGovernance2(parent, own ? "retireOwnWorkspace" : "retireWorkspace", payload, opts);
935
952
  } catch (e) {
936
953
  err3(e.message);
937
954
  return 1;
938
955
  }
939
956
  if (!v.ok) {
940
957
  err3(`retire '${ws}' refused (${v.status}): ${typeof v.body === "string" ? v.body : JSON.stringify(v.body)}`);
958
+ if (JSON.stringify(v.body ?? "").includes("retire-own-only")) {
959
+ err3(
960
+ `note: you appear to BE '${ws}'s creator \u2014 the parent's deployed governance law may predate the
961
+ 0.34.1 retireOwnWorkspace creator-normalization fix (the 'user:' subject prefix vs the bare uid).
962
+ A governance re-deploy to ${parent} fixes the self-service lane; meanwhile an ADMIN can retire it:
963
+ githolon ws retire ${ws} --as <admin-uid>`
964
+ );
965
+ }
941
966
  return 1;
942
967
  }
943
968
  out3(`\u2713 workspace ${ws} retired via signed governance offer to ${parent} on ${cloud}`);
@@ -4014,7 +4039,7 @@ var HELP = {
4014
4039
  },
4015
4040
  proof: {
4016
4041
  usage: "githolon proof [build/<name>.proof.mts] [--domain <key>] [--live] [--keep]",
4017
- what: "Run the proof GENERATED from your law. DEFAULT: the OFFLINE legs on a LOCAL holon \u2014 the\nsame engine plane the cloud edge runs; no cloud workspace is touched (develop/play/understand\nhere, deploy with confidence after). --domain <key> proves a SPECIFIC domain of a multi-domain\npackage (offline; the default is the first). --live runs the full cloud loop (throwaway\nworkspace \u2192 deploy \u2192 offline write \u2192 admission \u2192 cloud reads \u2192 convergence), RETIRED on every\nexit; --keep keeps it and prints the secret once. ALL GREEN or it names the jam. The offline\nlegs also rerun on every save in `githolon dev`.",
4042
+ what: "Run the proof GENERATED from your law. DEFAULT: the OFFLINE legs on a LOCAL holon \u2014 the\nsame engine plane the cloud edge runs; no cloud workspace is touched (develop/play/understand\nhere, deploy with confidence after). --domain <key> proves a SPECIFIC domain of a multi-domain\npackage (offline; the default is the first). --live runs the full cloud loop (throwaway\nworkspace \u2192 deploy \u2192 offline write \u2192 admission \u2192 cloud reads \u2192 convergence). The throwaway is\ncreated REGISTERED (a signed createWorkspace at root \u2014 your principal needs creation authority\nthere) and RETIRED on every exit via the lawful retireOwnWorkspace; --keep keeps it. ALL GREEN or it names the jam. The offline\nlegs also rerun on every save in `githolon dev`.",
4018
4043
  examples: ["githolon proof", "githolon proof --domain co2_platform", "githolon proof --live", "githolon proof --live --keep"]
4019
4044
  },
4020
4045
  dev: {
@@ -4899,13 +4924,58 @@ async function runProof(args) {
4899
4924
  const tsxPkg = JSON.parse(readFileSync11(join11(tsxDir, "package.json"), "utf8"));
4900
4925
  const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.["tsx"];
4901
4926
  const tsxCli = join11(tsxDir, tsxBinRel ?? "dist/cli.mjs");
4902
- console.log("githolon proof --live \u2014 the full cloud loop (throwaway workspace, retired on exit" + (keep ? "; --keep: kept, secret printed once" : "") + ")");
4927
+ console.log("githolon proof --live \u2014 the full cloud loop (throwaway workspace, retired on exit" + (keep ? "; --keep: kept" : "") + ")");
4928
+ const { wsCreate: wsCreate2, wsRetire: wsRetire2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
4929
+ const { resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
4930
+ const { login: login2, activePrincipal: activePrincipal2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
4931
+ let principal = process.env.NOMOS_PRINCIPAL;
4932
+ try {
4933
+ principal ??= resolveGovernancePrincipal2({});
4934
+ } catch {
4935
+ const lr = await login2({ agent: true });
4936
+ principal = lr === 0 ? activePrincipal2() : void 0;
4937
+ }
4938
+ if (principal === void 0) {
4939
+ return refuse("proof --live needs a principal \u2014 githolon login --agent (self-onboarding) failed; try it directly or pass NOMOS_PRINCIPAL");
4940
+ }
4941
+ const proofSlug = proofPath.split("/").pop().replace(/\.proof\.mts$/, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-");
4942
+ const ws = process.env.NOMOS_WS ?? `${proofSlug}-proof-${Math.random().toString(36).slice(2, 8)}`;
4943
+ if (process.env.NOMOS_WS === void 0) {
4944
+ const cr = await wsCreate2(ws, { via: "root", principal });
4945
+ if (cr !== 0) {
4946
+ return refuse(
4947
+ `proof --live: registered create refused at root \u2014 principal ${principal} lacks creation authority, and the open birth lane would leak an unretirable workspace.
4948
+ remedies:
4949
+ \u2022 ask an operator: githolon grant creation ${principal} (then rerun)
4950
+ \u2022 or pre-create a REGISTERED workspace yourself and hand it over: NOMOS_WS=<ws> githolon proof --live
4951
+ \u2022 or develop offline (no cloud workspace at all): githolon proof`
4952
+ );
4953
+ }
4954
+ }
4903
4955
  const r = spawnSync4(process.execPath, [tsxCli, proofPath], {
4904
4956
  stdio: "inherit",
4905
4957
  cwd: process.cwd(),
4906
- env: { ...process.env, ...keep ? { PROOF_KEEP: "1" } : {} }
4958
+ env: {
4959
+ ...process.env,
4960
+ NOMOS_WS: ws,
4961
+ NOMOS_PRINCIPAL: principal,
4962
+ NOMOS_PROOF_MANAGED: "1",
4963
+ // the proof skips its own (dead) cleanup lane; the CLI retires below
4964
+ ...keep ? { PROOF_KEEP: "1" } : {}
4965
+ }
4907
4966
  });
4908
- return r.status ?? 1;
4967
+ const proofStatus = r.status ?? 1;
4968
+ if (keep) {
4969
+ console.log(`workspace ${ws} KEPT (--keep) \u2014 retire it when done: githolon ws retire ${ws}`);
4970
+ return proofStatus;
4971
+ }
4972
+ const rr = await wsRetire2(ws, { principal }).catch(() => 1);
4973
+ if (rr !== 0) {
4974
+ console.error(`\u26A0 THROWAWAY WORKSPACE NOT RETIRED: ${ws}`);
4975
+ console.error(`\u26A0 retire it manually: githolon ws retire ${ws}`);
4976
+ console.error(`\u26A0 (if it has no root registry row it was born unregistered and needs a custodian sweep)`);
4977
+ }
4978
+ return proofStatus;
4909
4979
  }
4910
4980
  function parseArgs(argv) {
4911
4981
  const [command, ...rest] = argv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.34.0",
3
+ "version": "0.34.1",
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.34.0",
33
- "@githolon/dsl": "^0.34.0",
32
+ "@githolon/client": "^0.34.1",
33
+ "@githolon/dsl": "^0.34.1",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {