githolon 0.100.0 → 0.100.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 CHANGED
@@ -3098,6 +3098,8 @@ __export(governance_exports, {
3098
3098
  certifyEra: () => certifyEra,
3099
3099
  consentRebirth: () => consentRebirth,
3100
3100
  discoverSigningDomain: () => discoverSigningDomain,
3101
+ ensureSovereignHome: () => ensureSovereignHome,
3102
+ exchangeOnboardingToken: () => exchangeOnboardingToken,
3101
3103
  executeRepairRebirth: () => executeRepairRebirth,
3102
3104
  governanceOffer: () => governanceOffer,
3103
3105
  governanceRelay: () => governanceRelay,
@@ -3120,6 +3122,8 @@ __export(governance_exports, {
3120
3122
  resolveGovernancePrincipal: () => resolveGovernancePrincipal,
3121
3123
  signAndPostGovernance: () => signAndPostGovernance,
3122
3124
  signAndPostOffer: () => signAndPostOffer,
3125
+ signAndPostWorkspaceBirth: () => signAndPostWorkspaceBirth,
3126
+ signAndPostWorkspaceRetirement: () => signAndPostWorkspaceRetirement,
3123
3127
  validatePlanForApply: () => validatePlanForApply,
3124
3128
  verifyWorkspaceVerdict: () => verifyWorkspaceVerdict
3125
3129
  });
@@ -3195,28 +3199,239 @@ function canonicalPrincipal(principal) {
3195
3199
  return s.includes(":") ? s : `user:${s}`;
3196
3200
  }
3197
3201
  async function signAndPostOffer(ws, domain, directiveId, payload, opts) {
3202
+ return signAndPostPreparedOffer(ws, domain, () => ({ directiveId, payload }), opts);
3203
+ }
3204
+ async function signAndPostPreparedOffer(ws, domain, prepare, opts, authorMode = "account", preferActor) {
3198
3205
  const cloud = cloudBase(opts.cloud);
3199
3206
  const principal = resolveGovernancePrincipal(opts);
3200
3207
  const holon = await connectGovernance(cloud, ws);
3201
- const resolvedDomain = domain ?? await discoverSigningDomain(holon, ws, directiveId, void 0);
3202
3208
  const device = await ensureDeviceKey(holon, principal);
3209
+ const accountActor = canonicalPrincipal(principal);
3210
+ const keyActor = `key:${device.keyHash}`;
3211
+ let actor = accountActor;
3212
+ if (preferActor !== void 0 && preferActor === keyActor) {
3213
+ actor = keyActor;
3214
+ } else if (preferActor !== void 0 && sameIdentity(preferActor, accountActor)) {
3215
+ actor = accountActor;
3216
+ } else if (authorMode === "self-if-unenrolled" && typeof holon.parentSignerEnrollment === "function") {
3217
+ try {
3218
+ const posture = await holon.parentSignerEnrollment({ parent: ws, principal: accountActor, keyHash: device.keyHash });
3219
+ if (!posture.enrolled) actor = keyActor;
3220
+ } catch {
3221
+ }
3222
+ }
3223
+ const prepared = prepare(actor);
3224
+ const resolvedDomain = domain ?? await discoverSigningDomain(holon, ws, prepared.directiveId, void 0);
3203
3225
  const sealed = await holon.signGovernanceOffer({
3204
3226
  domain: resolvedDomain,
3205
- directiveId,
3206
- payload,
3227
+ directiveId: prepared.directiveId,
3228
+ payload: prepared.payload,
3207
3229
  authorSecret: device.secret,
3208
- actor: canonicalPrincipal(principal)
3230
+ actor
3209
3231
  });
3210
3232
  if (sealed.intentBytes.length > STAGE_THRESHOLD_CHARS) {
3211
- const staged = await relaySealedOfferViaStage(cloud, ws, directiveId, sealed.intentBytes, fetch);
3233
+ const staged = await relaySealedOfferViaStage(cloud, ws, prepared.directiveId, sealed.intentBytes, fetch);
3212
3234
  if (staged !== null) {
3213
3235
  out2(` staged ${staged.size} sealed bytes content-addressed (sha256 ${staged.sha256.slice(0, 16)}\u2026) \u2014 the signed offer names the hash`);
3214
- return { ...staged.verdict, principal };
3236
+ return { ...staged.verdict, principal, actor, directiveId: prepared.directiveId };
3215
3237
  }
3216
3238
  err2(`this cloud has no /v2/stage content-addressed lane \u2014 relaying the ${sealed.intentBytes.length}-char sealed offer inline (a 413 here means the worker needs upgrading to accept law this large signed)`);
3217
3239
  }
3218
- const verdict = await holon.postGovernanceOffer({ directiveId, intentBytes: sealed.intentBytes, ws, domain: resolvedDomain });
3219
- return { ...verdict, principal };
3240
+ const verdict = await holon.postGovernanceOffer({ directiveId: prepared.directiveId, intentBytes: sealed.intentBytes, ws, domain: resolvedDomain });
3241
+ return { ...verdict, principal, actor, directiveId: prepared.directiveId };
3242
+ }
3243
+ async function signAndPostWorkspaceBirth(parent, name, opts) {
3244
+ return signAndPostPreparedOffer(
3245
+ parent,
3246
+ "workspaces",
3247
+ (actor) => {
3248
+ const identity = lineageIdentity(actor);
3249
+ return {
3250
+ directiveId: "createWorkspace",
3251
+ payload: {
3252
+ name,
3253
+ tier: "edge",
3254
+ parent: parent === "root" ? "" : parent,
3255
+ principal: identity,
3256
+ requestedBy: identity,
3257
+ requestedAt: Date.now()
3258
+ }
3259
+ };
3260
+ },
3261
+ opts,
3262
+ "self-if-unenrolled"
3263
+ );
3264
+ }
3265
+ async function exchangeOnboardingToken(session, keyHash, idp = process.env["NOMOS_ONBOARDING_IDP"] ?? DEFAULT_ONBOARDING_IDP, fetchImpl = fetch) {
3266
+ const r = await fetchImpl(`${idp.replace(/\/+$/, "")}/token`, {
3267
+ method: "POST",
3268
+ headers: { authorization: `Bearer ${session}`, "content-type": "application/json" },
3269
+ body: JSON.stringify({ nonce: keyHash })
3270
+ });
3271
+ const body = await r.json().catch(() => null);
3272
+ if (!r.ok || typeof body?.token !== "string" || typeof body.issuer !== "string" || typeof body.subject !== "string") {
3273
+ throw new Error(
3274
+ `Nomos could not establish the first device identity (${r.status}): ${String(body?.error ?? "invalid identity-provider response")}`
3275
+ );
3276
+ }
3277
+ return { token: body.token, issuer: body.issuer, subject: body.subject };
3278
+ }
3279
+ async function ensureSovereignHome(opts = {}) {
3280
+ const cloud = cloudBase(opts.cloud);
3281
+ const uid = opts.principal ?? currentPrincipal();
3282
+ if (!uid) throw new Error("a Nomos session is required \u2014 githolon login --agent");
3283
+ const actor = canonicalPrincipal(uid);
3284
+ if (!actor.startsWith("user:")) throw new Error("blank-session bootstrap requires an identity-provider principal");
3285
+ const bare = actor.slice("user:".length);
3286
+ const auth = await sessionToken();
3287
+ if (!auth) throw new Error("blank-session bootstrap needs the live login session \u2014 githolon login --agent");
3288
+ const client = await import("@githolon/client");
3289
+ const home = await client.homeNameOf(actor);
3290
+ const exists = await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false);
3291
+ const root = await connectGovernance(cloud, "root");
3292
+ const device = await ensureDeviceKey(root, bare);
3293
+ let signerReady = false;
3294
+ if (typeof root.parentSignerEnrollment === "function") {
3295
+ signerReady = await root.parentSignerEnrollment({ parent: "root", principal: actor, keyHash: device.keyHash, authToken: auth }).then((p) => p.enrolled && p.revoked !== true).catch(() => false);
3296
+ }
3297
+ const delegationReady = await fetch(
3298
+ `${cloud}/v2/workspaces/root/workspaces/signerDelegationByUser?user=${encodeURIComponent(actor)}`
3299
+ ).then(async (r) => {
3300
+ if (!r.ok) return false;
3301
+ const d = await r.json();
3302
+ return Array.isArray(d.rows) && d.rows.length > 0;
3303
+ }).catch(() => false);
3304
+ if (!signerReady || !delegationReady) {
3305
+ if (typeof root.enrollFirstDevice !== "function") {
3306
+ throw new Error("the installed @githolon/client predates automatic first-device enrollment");
3307
+ }
3308
+ const assertion = await exchangeOnboardingToken(auth, device.keyHash);
3309
+ if (assertion.subject !== bare) {
3310
+ throw new Error(`identity provider returned '${assertion.subject}' for logged-in principal '${bare}'`);
3311
+ }
3312
+ await root.enrollFirstDevice({
3313
+ parent: "root",
3314
+ domain: "workspaces",
3315
+ principal: actor,
3316
+ device,
3317
+ idToken: assertion.token,
3318
+ authToken: assertion.token,
3319
+ verifiedVia: assertion.issuer
3320
+ });
3321
+ }
3322
+ if (!exists) {
3323
+ const domains = await fetch(`${cloud}/v2/workspaces/root/domains`).then(async (r) => {
3324
+ if (!r.ok) throw new Error(`root law discovery failed (${r.status})`);
3325
+ return await r.json();
3326
+ });
3327
+ const frameworkHash = domains.currentLaw?.["nomos"];
3328
+ const lawHash = domains.currentLaw?.["workspaces"];
3329
+ if (!frameworkHash || !lawHash) throw new Error("root does not report the framework and governance laws needed for birth");
3330
+ const birthCert = await root.certSign({
3331
+ child: home,
3332
+ founder: actor,
3333
+ verified: true,
3334
+ parentKey: device.public,
3335
+ parentId: "root",
3336
+ epoch: 0,
3337
+ secret: device.secret
3338
+ });
3339
+ const now = Date.now();
3340
+ const birth = await fetch(`${cloud}/v2/workspaces/root/workspaces/birthChild`, {
3341
+ method: "POST",
3342
+ headers: { "content-type": "application/json" },
3343
+ body: JSON.stringify({
3344
+ name: home,
3345
+ parent: "",
3346
+ principal: bare,
3347
+ tier: "edge",
3348
+ requestedBy: bare,
3349
+ requestedAt: now,
3350
+ foundingAdminHash: device.keyHash,
3351
+ bornAt: new Date(now).toISOString(),
3352
+ frameworkHash,
3353
+ lawHash,
3354
+ platformCert: JSON.stringify(birthCert),
3355
+ actor,
3356
+ authorSecret: device.secret
3357
+ })
3358
+ });
3359
+ const body = await birth.json().catch(() => null);
3360
+ const failed = body?.birthOutcomes?.find((o) => o.status !== "born");
3361
+ if (!birth.ok || body?.ok === false || failed) {
3362
+ throw new Error(
3363
+ `Nomos could not birth the session home (${birth.status}): ${failed?.reason ?? String(body?.error ?? JSON.stringify(body))}`
3364
+ );
3365
+ }
3366
+ const deadline = Date.now() + 3e4;
3367
+ while (Date.now() < deadline) {
3368
+ if (await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false)) break;
3369
+ await new Promise((resolve6) => setTimeout(resolve6, 250));
3370
+ }
3371
+ if (!await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false)) {
3372
+ throw new Error(`Nomos admitted the birth of '${home}' but its custody did not become readable`);
3373
+ }
3374
+ const admin = await signAndPostOffer(
3375
+ home,
3376
+ "workspaces",
3377
+ "grantAdmin",
3378
+ { principal: bare, label: "founding admin", grantedBy: bare, grantedAt: now },
3379
+ { ...opts, principal: bare }
3380
+ );
3381
+ if (!admin.ok) throw new Error(`the born home refused its founding admin (${admin.status}): ${JSON.stringify(admin.body)}`);
3382
+ }
3383
+ const homeHolon = await connectGovernance(cloud, home);
3384
+ const homeSigner = typeof homeHolon.parentSignerEnrollment === "function" ? await homeHolon.parentSignerEnrollment({ parent: home, principal: actor, keyHash: device.keyHash, authToken: auth }).catch(() => null) : null;
3385
+ if (!homeSigner?.verifiedVia) {
3386
+ if (typeof homeHolon.enrollFirstDevice !== "function") {
3387
+ throw new Error("the installed @githolon/client predates verified session-home enrollment");
3388
+ }
3389
+ const assertion = await exchangeOnboardingToken(auth, device.keyHash);
3390
+ if (assertion.subject !== bare) {
3391
+ throw new Error(`identity provider returned '${assertion.subject}' for logged-in principal '${bare}'`);
3392
+ }
3393
+ const domain = await discoverSigningDomain(homeHolon, home, "enrollFirstDevice", "workspaces");
3394
+ await homeHolon.enrollFirstDevice({
3395
+ parent: home,
3396
+ domain,
3397
+ principal: actor,
3398
+ device,
3399
+ idToken: assertion.token,
3400
+ authToken: assertion.token,
3401
+ verifiedVia: assertion.issuer,
3402
+ includeDelegation: false
3403
+ });
3404
+ const object = `identity:${actor}`;
3405
+ const deadline = Date.now() + 3e4;
3406
+ let visible = false;
3407
+ while (Date.now() < deadline) {
3408
+ visible = await fetch(
3409
+ `${cloud}/v2/workspaces/${encodeURIComponent(home)}/workspaces/relationTuplesByObject?object=${encodeURIComponent(object)}`
3410
+ ).then(async (r) => {
3411
+ if (!r.ok) return false;
3412
+ const body = await r.json();
3413
+ const leaf = body.rows?.[0]?.data?.subjects?.[`key:${device.keyHash}`];
3414
+ return typeof leaf?.verifiedVia === "string" && leaf.verifiedVia.length > 0;
3415
+ }).catch(() => false);
3416
+ if (visible) break;
3417
+ await new Promise((resolve6) => setTimeout(resolve6, 250));
3418
+ }
3419
+ if (!visible) throw new Error(`the session home's verified device enrollment did not become readable`);
3420
+ }
3421
+ return { home, principal: actor, device, created: !exists };
3422
+ }
3423
+ async function signAndPostWorkspaceRetirement(parent, workspaceId, creator, opts) {
3424
+ return signAndPostPreparedOffer(
3425
+ parent,
3426
+ "workspaces",
3427
+ (actor) => ({
3428
+ directiveId: creator !== "" && sameIdentity(creator, actor) ? "retireOwnWorkspace" : "retireWorkspace",
3429
+ payload: { workspaceId, retiredBy: lineageIdentity(actor), retiredAt: Date.now() }
3430
+ }),
3431
+ opts,
3432
+ "self-if-unenrolled",
3433
+ creator
3434
+ );
3220
3435
  }
3221
3436
  async function relaySealedOfferViaStage(cloud, ws, directiveId, intentBytesB64, fetchImpl) {
3222
3437
  const raw = Buffer.from(intentBytesB64, "base64");
@@ -4517,13 +4732,16 @@ function readSealedIntentBytes(eng, ws, intentOut) {
4517
4732
  if (f?.data === void 0) return void 0;
4518
4733
  return Buffer.from(f.data).toString("base64");
4519
4734
  }
4520
- var out2, err2, STAGE_THRESHOLD_CHARS, HONEST_CEILING, ROOT_CUSTODIAN_SECRET, CLIENT_IMPACT;
4735
+ var out2, err2, lineageIdentity, sameIdentity, DEFAULT_ONBOARDING_IDP, STAGE_THRESHOLD_CHARS, HONEST_CEILING, ROOT_CUSTODIAN_SECRET, CLIENT_IMPACT;
4521
4736
  var init_governance = __esm({
4522
4737
  "src/governance.ts"() {
4523
4738
  "use strict";
4524
4739
  init_cloud();
4525
4740
  out2 = (s) => void process.stdout.write(s + "\n");
4526
4741
  err2 = (s) => void process.stderr.write("error: " + s + "\n");
4742
+ lineageIdentity = (actor) => actor.startsWith("user:") ? actor.slice("user:".length) : actor;
4743
+ sameIdentity = (a, b) => lineageIdentity(a) === lineageIdentity(b);
4744
+ DEFAULT_ONBOARDING_IDP = "https://id.nomos.captainapp.co.uk";
4527
4745
  STAGE_THRESHOLD_CHARS = 4 * 1024 * 1024;
4528
4746
  HONEST_CEILING = `The operator controls root's law and could deploy law removing the consent check \u2014 but that act is itself a signed, ordered, permanent fact in root's chain, visible to every tenant running \`replay root\`, and grounds for exit-with-everything. Not "we can't" \u2014 "we can't secretly, and you can always leave."`;
4529
4747
  ROOT_CUSTODIAN_SECRET = "nomos-root-custodian-key";
@@ -5181,16 +5399,10 @@ async function logout() {
5181
5399
  async function wsCreate(name, opts) {
5182
5400
  const cloud = cloudBase(opts.cloud);
5183
5401
  if (opts.via !== void 0) {
5184
- const { signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5402
+ const { signAndPostWorkspaceBirth: signAndPostWorkspaceBirth2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5185
5403
  let v;
5186
5404
  try {
5187
- const principal2 = resolveGovernancePrincipal2(opts);
5188
- v = await signAndPostGovernance2(
5189
- opts.via,
5190
- "createWorkspace",
5191
- { name, tier: "edge", parent: opts.via === "root" ? "" : opts.via, principal: principal2, requestedBy: principal2, requestedAt: Date.now() },
5192
- opts
5193
- );
5405
+ v = await signAndPostWorkspaceBirth2(opts.via, name, opts);
5194
5406
  } catch (e) {
5195
5407
  err4(e.message);
5196
5408
  return 1;
@@ -5259,7 +5471,7 @@ async function wsStatus(name, opts) {
5259
5471
  }
5260
5472
  async function wsRetire(ws, opts) {
5261
5473
  const cloud = cloudBase(opts.cloud);
5262
- const { signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5474
+ const { signAndPostWorkspaceRetirement: signAndPostWorkspaceRetirement2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5263
5475
  const parent = opts.parent ?? "root";
5264
5476
  let record;
5265
5477
  try {
@@ -5280,12 +5492,8 @@ async function wsRetire(ws, opts) {
5280
5492
  }
5281
5493
  let v;
5282
5494
  try {
5283
- const principal = resolveGovernancePrincipal2(opts);
5284
- const payload = { workspaceId: recordId, retiredBy: principal, retiredAt: Date.now() };
5285
- const bare = (s) => s.startsWith("user:") ? s.slice(5) : s;
5286
5495
  const creator = record?.data?.createdBy ?? record?.data?.principal ?? "";
5287
- const own = creator !== "" && bare(creator) === bare(principal);
5288
- v = await signAndPostGovernance2(parent, own ? "retireOwnWorkspace" : "retireWorkspace", payload, opts);
5496
+ v = await signAndPostWorkspaceRetirement2(parent, recordId, creator, opts);
5289
5497
  } catch (e) {
5290
5498
  err4(e.message);
5291
5499
  return 1;
@@ -8840,9 +9048,9 @@ var HELP = {
8840
9048
  examples: ["githolon compile", "githolon compile nomos.package.mjs --layered"]
8841
9049
  },
8842
9050
  proof: {
8843
- usage: "githolon proof [build/<name>.proof.mts] [--domain <key>] [--live] [--keep]",
9051
+ usage: "githolon proof [build/<name>.proof.mts] [--domain <key>] [--live]",
8844
9052
  what: "Run the proof GENERATED from your business law. By default it drives the real local engine:\nbirth, full-history verification, durable custody, eviction, restore, and read-back. --live runs the\nsame business proof against Nomos Cloud; identity, provisioning, persistence, and cleanup remain\ninside Nomos. --domain selects one domain in a multi-domain package. ALL GREEN or it names the jam.",
8845
- examples: ["githolon proof", "githolon proof --domain co2_platform", "githolon proof --live", "githolon proof --live --keep"]
9053
+ examples: ["githolon proof", "githolon proof --domain co2_platform", "githolon proof --live"]
8846
9054
  },
8847
9055
  dev: {
8848
9056
  usage: "githolon dev [--port <n>] [--cloud <url>] [--once]",
@@ -9706,8 +9914,7 @@ async function runProof(args) {
9706
9914
  return 1;
9707
9915
  };
9708
9916
  const live = args.includes("--live");
9709
- const keep = args.includes("--keep");
9710
- if (keep && !live) return refuse("--keep only applies to --live (the offline proof creates no cloud workspace to keep)");
9917
+ if (args.includes("--keep")) return refuse("--keep no longer applies: proof --live uses your durable signed Nomos home and creates only the requested business aggregate");
9711
9918
  let domain;
9712
9919
  let domainValueIdx = -1;
9713
9920
  const di = args.findIndex((a) => a === "--domain" || a.startsWith("--domain="));
@@ -9774,54 +9981,40 @@ async function runProof(args) {
9774
9981
  const tsxPkg = JSON.parse(readFileSync16(join17(tsxDir, "package.json"), "utf8"));
9775
9982
  const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.["tsx"];
9776
9983
  const tsxCli = join17(tsxDir, tsxBinRel ?? "dist/cli.mjs");
9777
- console.log("githolon proof --live \u2014 the generated business proof against Nomos Cloud" + (keep ? " (--keep preserves its temporary custody)" : ""));
9778
- const { wsCreate: wsCreate2, wsRetire: wsRetire2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
9779
- const { resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
9780
- const { login: login2, activePrincipal: activePrincipal2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
9781
- let principal = process.env.NOMOS_PRINCIPAL;
9782
- try {
9783
- principal ??= resolveGovernancePrincipal2({});
9784
- } catch {
9785
- const lr = await login2({ agent: true });
9786
- principal = lr === 0 ? activePrincipal2() : void 0;
9984
+ console.log("githolon proof --live \u2014 one generated app.birth against Nomos Cloud");
9985
+ const { ensureSovereignHome: ensureSovereignHome2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
9986
+ if (currentPrincipal() === void 0) {
9987
+ const lr = await login({ agent: true });
9988
+ if (lr !== 0) {
9989
+ return refuse("proof --live needs a login \u2014 githolon login --agent failed; try it directly");
9990
+ }
9787
9991
  }
9788
- if (principal === void 0) {
9992
+ if (currentPrincipal() === void 0) {
9789
9993
  return refuse("proof --live needs a principal \u2014 githolon login --agent (self-onboarding) failed; try it directly or pass NOMOS_PRINCIPAL");
9790
9994
  }
9791
- const proofSlug = proofPath.split("/").pop().replace(/\.proof\.mts$/, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-");
9792
- const ws = process.env.NOMOS_WS ?? `${proofSlug}-proof-${Math.random().toString(36).slice(2, 8)}`;
9793
- if (process.env.NOMOS_WS === void 0) {
9794
- const cr = await wsCreate2(ws, { via: "root", principal });
9795
- if (cr !== 0) {
9796
- return refuse(
9797
- `proof --live: Nomos could not establish safe custody for birth as ${principal}. This is a framework failure: no manual grant, key, parent, or provisioning step is part of the application contract. The local business proof remains available with: githolon proof`
9798
- );
9799
- }
9995
+ let home;
9996
+ try {
9997
+ home = await ensureSovereignHome2();
9998
+ } catch (e) {
9999
+ return refuse(
10000
+ `proof --live: Nomos could not establish the signed session home: ${e.message}. No certificate, signer, parent, or provisioning step is part of the application contract.`
10001
+ );
9800
10002
  }
10003
+ const barePrincipal = home.principal.startsWith("user:") ? home.principal.slice("user:".length) : home.principal;
10004
+ const deployed = await deploy2(home.home, { principal: barePrincipal });
10005
+ if (deployed !== 0) return refuse("proof --live: Nomos could not install the compiled business law into the signed session home");
9801
10006
  const r = spawnSync6(process.execPath, [tsxCli, proofPath], {
9802
10007
  stdio: "inherit",
9803
10008
  cwd: process.cwd(),
9804
10009
  env: {
9805
10010
  ...process.env,
9806
- NOMOS_WS: ws,
9807
- NOMOS_PRINCIPAL: principal,
9808
- NOMOS_PROOF_MANAGED: "1",
9809
- // the proof skips its own (dead) cleanup lane; the CLI retires below
9810
- ...keep ? { PROOF_KEEP: "1" } : {}
10011
+ NOMOS_WS: home.home,
10012
+ NOMOS_PRINCIPAL: home.principal,
10013
+ NOMOS_AUTHOR_SECRET: home.device.secret,
10014
+ NOMOS_PROOF_MANAGED: "1"
9811
10015
  }
9812
10016
  });
9813
- const proofStatus = r.status ?? 1;
9814
- if (keep) {
9815
- console.log(`workspace ${ws} KEPT (--keep) \u2014 retire it when done: githolon ws retire ${ws}`);
9816
- return proofStatus;
9817
- }
9818
- const rr = await wsRetire2(ws, { principal }).catch(() => 1);
9819
- if (rr !== 0) {
9820
- console.error(`\u26A0 THROWAWAY WORKSPACE NOT RETIRED: ${ws}`);
9821
- console.error(`\u26A0 retire it manually: githolon ws retire ${ws}`);
9822
- console.error(`\u26A0 (if it has no root registry row it was born unregistered and needs a custodian sweep)`);
9823
- }
9824
- return proofStatus;
10017
+ return r.status ?? 1;
9825
10018
  }
9826
10019
  function parseArgs(argv) {
9827
10020
  const [command, ...rest] = argv;
@@ -1851,7 +1851,21 @@ function resolveGatewayOperation(spec, opName, method) {
1851
1851
  const exactPath = `/${String(opName).replace(/^\/+/, "")}`;
1852
1852
  const exact = spec.paths[exactPath]?.[normalizedMethod];
1853
1853
  if (exact) return { op: exact, path: exactPath, ambiguous: null };
1854
- if (String(opName).includes("/")) return { op: null };
1854
+ const slash = String(opName).indexOf("/");
1855
+ if (slash > 0) {
1856
+ const requestedDomain = String(opName).slice(0, slash);
1857
+ const requestedAlias = String(opName).slice(slash + 1);
1858
+ const matches2 = [];
1859
+ for (const [path2, methods] of Object.entries(spec.paths)) {
1860
+ const op = methods?.[normalizedMethod];
1861
+ const x = op?.["x-nomos"];
1862
+ if (!op || !x || x.domain !== requestedDomain) continue;
1863
+ if (aliasIdsFor(x, path2).has(requestedAlias)) matches2.push({ op, path: path2 });
1864
+ }
1865
+ if (matches2.length === 1) return { ...matches2[0], ambiguous: null };
1866
+ if (matches2.length > 1) return { op: null, ambiguous: matches2.map((m) => m.path).sort() };
1867
+ return { op: null, ambiguous: null };
1868
+ }
1855
1869
  const matches = [];
1856
1870
  for (const [path2, methods] of Object.entries(spec.paths)) {
1857
1871
  const op = methods?.[normalizedMethod];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.100.0",
3
+ "version": "0.100.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.100.0",
33
- "@githolon/dsl": "^0.100.0",
32
+ "@githolon/client": "^0.100.1",
33
+ "@githolon/dsl": "^0.100.1",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {