githolon 0.100.2 → 0.100.3

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 +72 -15
  2. package/package.json +3 -3
package/dist/cli.mjs CHANGED
@@ -3120,6 +3120,7 @@ __export(governance_exports, {
3120
3120
  renderRebirthImpact: () => renderRebirthImpact,
3121
3121
  resolveGovernanceHash: () => resolveGovernanceHash,
3122
3122
  resolveGovernancePrincipal: () => resolveGovernancePrincipal,
3123
+ signAndPostChildLifecycle: () => signAndPostChildLifecycle,
3123
3124
  signAndPostGovernance: () => signAndPostGovernance,
3124
3125
  signAndPostOffer: () => signAndPostOffer,
3125
3126
  signAndPostWorkspaceBirth: () => signAndPostWorkspaceBirth,
@@ -3433,6 +3434,22 @@ async function signAndPostWorkspaceRetirement(parent, workspaceId, creator, opts
3433
3434
  creator
3434
3435
  );
3435
3436
  }
3437
+ async function signAndPostChildLifecycle(parent, child, creator, action, opts) {
3438
+ return signAndPostPreparedOffer(
3439
+ parent,
3440
+ void 0,
3441
+ (actor) => action === "retire" ? {
3442
+ directiveId: "retireChild",
3443
+ payload: { child, principal: creator, retiredBy: lineageIdentity(actor), retiredAt: Date.now() }
3444
+ } : {
3445
+ directiveId: "reclaimChild",
3446
+ payload: { child, reclaimedBy: lineageIdentity(actor), reclaimedAt: Date.now() }
3447
+ },
3448
+ opts,
3449
+ "self-if-unenrolled",
3450
+ creator
3451
+ );
3452
+ }
3436
3453
  async function relaySealedOfferViaStage(cloud, ws, directiveId, intentBytesB64, fetchImpl) {
3437
3454
  const raw = Buffer.from(intentBytesB64, "base64");
3438
3455
  const sha2562 = createHash("sha256").update(raw).digest("hex");
@@ -5471,9 +5488,19 @@ async function wsStatus(name, opts) {
5471
5488
  out4(text);
5472
5489
  return 0;
5473
5490
  }
5491
+ async function childBirthRecord(cloud, parent, child) {
5492
+ try {
5493
+ const id = `nomos-birth-record:${child}`;
5494
+ const r = await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(parent)}/aggregates/${encodeURIComponent(id)}`);
5495
+ const body = await r.json().catch(() => void 0);
5496
+ return body?.ok === true ? body.rows?.find((row) => row.data?.child === child) : void 0;
5497
+ } catch {
5498
+ return void 0;
5499
+ }
5500
+ }
5474
5501
  async function wsRetire(ws, opts) {
5475
5502
  const cloud = cloudBase(opts.cloud);
5476
- const { signAndPostWorkspaceRetirement: signAndPostWorkspaceRetirement2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5503
+ const { signAndPostChildLifecycle: signAndPostChildLifecycle2, signAndPostWorkspaceRetirement: signAndPostWorkspaceRetirement2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5477
5504
  const parent = opts.parent ?? "root";
5478
5505
  let record;
5479
5506
  try {
@@ -5485,12 +5512,29 @@ async function wsRetire(ws, opts) {
5485
5512
  }
5486
5513
  const recordId = record?.id;
5487
5514
  if (recordId === void 0) {
5488
- err4(
5489
- `retire '${ws}': no CloudWorkspace record named '${ws}' in ${parent}'s registry \u2014 nothing lawful to retire.
5490
- (a workspace born via the OPEN lane \u2014 bare POST /v2/workspaces/${ws} \u2014 has no registry row;
5491
- registered births ride \`githolon ws create ${ws} --via ${parent}\`. An unregistered leak needs a custodian sweep.)`
5492
- );
5493
- return 1;
5515
+ const childRecord = await childBirthRecord(cloud, parent, ws);
5516
+ if (childRecord === void 0) {
5517
+ err4(
5518
+ `retire '${ws}': no CloudWorkspace or NomosBirthRecord named '${ws}' in ${parent}'s registry \u2014 nothing lawful to retire.
5519
+ An out-of-band custody repo has no parent lifecycle fact and needs a custodian investigation.`
5520
+ );
5521
+ return 1;
5522
+ }
5523
+ const creator = childRecord.data?.principal ?? "";
5524
+ let childVerdict;
5525
+ try {
5526
+ childVerdict = await signAndPostChildLifecycle2(parent, ws, creator, "retire", opts);
5527
+ } catch (e) {
5528
+ err4(e.message);
5529
+ return 1;
5530
+ }
5531
+ if (!childVerdict.ok) {
5532
+ err4(`retire '${ws}' refused (${childVerdict.status}): ${typeof childVerdict.body === "string" ? childVerdict.body : JSON.stringify(childVerdict.body)}`);
5533
+ return 1;
5534
+ }
5535
+ out4(`\u2713 child ${ws} retired via signed lifecycle offer to ${parent} on ${cloud}`);
5536
+ out4(" custody is retained; reclaim is a separate, law-gated terminal step");
5537
+ return 0;
5494
5538
  }
5495
5539
  let v;
5496
5540
  try {
@@ -5519,17 +5563,30 @@ async function wsRetire(ws, opts) {
5519
5563
  }
5520
5564
  async function wsReclaim(ws, opts) {
5521
5565
  const cloud = cloudBase(opts.cloud);
5522
- const { signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5566
+ const { signAndPostChildLifecycle: signAndPostChildLifecycle2, signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5523
5567
  const parent = opts.parent ?? "root";
5524
5568
  let v;
5525
5569
  try {
5526
5570
  const principal = resolveGovernancePrincipal2(opts);
5527
- v = await signAndPostGovernance2(
5528
- parent,
5529
- "reclaimWorkspace",
5530
- { workspaceId: ws, reclaimedBy: principal, reclaimedAt: Date.now() },
5531
- opts
5532
- );
5571
+ const q = await fetch(`${cloud}/v2/workspaces/${parent}/workspaceByName?name=${encodeURIComponent(ws)}`);
5572
+ const qd = await q.json().catch(() => void 0);
5573
+ const rows = qd?.ok === true ? qd.rows ?? [] : [];
5574
+ const workspace = rows.find((r) => r.data?.status === "retired") ?? rows[0];
5575
+ if (workspace?.id !== void 0) {
5576
+ v = await signAndPostGovernance2(
5577
+ parent,
5578
+ "reclaimWorkspace",
5579
+ { workspaceId: workspace.id, reclaimedBy: principal, reclaimedAt: Date.now() },
5580
+ opts
5581
+ );
5582
+ } else {
5583
+ const child = await childBirthRecord(cloud, parent, ws);
5584
+ if (child === void 0) {
5585
+ err4(`reclaim '${ws}': no CloudWorkspace or NomosBirthRecord named '${ws}' in ${parent}'s registry`);
5586
+ return 1;
5587
+ }
5588
+ v = await signAndPostChildLifecycle2(parent, ws, child.data?.principal ?? "", "reclaim", opts);
5589
+ }
5533
5590
  } catch (e) {
5534
5591
  err4(e.message);
5535
5592
  return 1;
@@ -5538,7 +5595,7 @@ async function wsReclaim(ws, opts) {
5538
5595
  err4(`reclaim '${ws}' refused (${v.status}): ${typeof v.body === "string" ? v.body : JSON.stringify(v.body)}`);
5539
5596
  return 1;
5540
5597
  }
5541
- out4(`\u2713 workspace ${ws} reclaimed via signed governance offer to ${parent} on ${cloud}`);
5598
+ out4(`\u2713 workspace ${ws} reclaimed via signed lifecycle offer to ${parent} on ${cloud}`);
5542
5599
  out4(" the custodian drops the ledger bytes on seeing this fact folded; the reclaimed FACT is append-only");
5543
5600
  return 0;
5544
5601
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.100.2",
3
+ "version": "0.100.3",
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.100.2",
33
- "@githolon/dsl": "^0.100.2",
32
+ "@githolon/client": "^0.100.3",
33
+ "@githolon/dsl": "^0.100.3",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {