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 +257 -64
- package/dist/dev-server.mjs +15 -1
- package/package.json +3 -3
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
|
|
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 {
|
|
5402
|
+
const { signAndPostWorkspaceBirth: signAndPostWorkspaceBirth2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
5185
5403
|
let v;
|
|
5186
5404
|
try {
|
|
5187
|
-
|
|
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 {
|
|
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
|
-
|
|
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]
|
|
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"
|
|
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
|
-
|
|
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
|
|
9778
|
-
const {
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
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 (
|
|
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
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
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:
|
|
9807
|
-
NOMOS_PRINCIPAL: principal,
|
|
9808
|
-
|
|
9809
|
-
|
|
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
|
-
|
|
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;
|
package/dist/dev-server.mjs
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
33
|
-
"@githolon/dsl": "^0.100.
|
|
32
|
+
"@githolon/client": "^0.100.1",
|
|
33
|
+
"@githolon/dsl": "^0.100.1",
|
|
34
34
|
"isomorphic-git": "^1.38.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|