githolon 0.100.3 → 0.100.5
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 +157 -6
- package/dist/dev-server.mjs +23 -13
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -3098,6 +3098,7 @@ __export(governance_exports, {
|
|
|
3098
3098
|
certifyEra: () => certifyEra,
|
|
3099
3099
|
consentRebirth: () => consentRebirth,
|
|
3100
3100
|
discoverSigningDomain: () => discoverSigningDomain,
|
|
3101
|
+
ensureApplicationWorkspace: () => ensureApplicationWorkspace,
|
|
3101
3102
|
ensureSovereignHome: () => ensureSovereignHome,
|
|
3102
3103
|
exchangeOnboardingToken: () => exchangeOnboardingToken,
|
|
3103
3104
|
executeRepairRebirth: () => executeRepairRebirth,
|
|
@@ -3277,6 +3278,20 @@ async function exchangeOnboardingToken(session, keyHash, idp = process.env["NOMO
|
|
|
3277
3278
|
}
|
|
3278
3279
|
return { token: body.token, issuer: body.issuer, subject: body.subject };
|
|
3279
3280
|
}
|
|
3281
|
+
async function workspaceMainHead(cloud, workspace) {
|
|
3282
|
+
return fetch(
|
|
3283
|
+
`${cloud}/v2/workspaces/${encodeURIComponent(workspace)}/git/info/refs?service=git-upload-pack`
|
|
3284
|
+
).then(async (r) => r.ok ? /([0-9a-f]{40}) refs\/heads\/main\b/.exec(await r.text())?.[1] : void 0).catch(() => void 0);
|
|
3285
|
+
}
|
|
3286
|
+
async function waitForWorkspaceMain(cloud, workspace, timeoutMs = 3e4) {
|
|
3287
|
+
const deadline = Date.now() + timeoutMs;
|
|
3288
|
+
while (Date.now() < deadline) {
|
|
3289
|
+
const head = await workspaceMainHead(cloud, workspace);
|
|
3290
|
+
if (head !== void 0) return head;
|
|
3291
|
+
await new Promise((resolve6) => setTimeout(resolve6, 250));
|
|
3292
|
+
}
|
|
3293
|
+
return void 0;
|
|
3294
|
+
}
|
|
3280
3295
|
async function ensureSovereignHome(opts = {}) {
|
|
3281
3296
|
const cloud = cloudBase(opts.cloud);
|
|
3282
3297
|
const uid = opts.principal ?? currentPrincipal();
|
|
@@ -3421,6 +3436,123 @@ async function ensureSovereignHome(opts = {}) {
|
|
|
3421
3436
|
}
|
|
3422
3437
|
return { home, principal: actor, device, created: !exists };
|
|
3423
3438
|
}
|
|
3439
|
+
async function ensureApplicationWorkspace(application, opts = {}) {
|
|
3440
|
+
const cloud = cloudBase(opts.cloud);
|
|
3441
|
+
const statusUrl = `${cloud}/v2/workspaces/${encodeURIComponent(application)}`;
|
|
3442
|
+
const current = await fetch(statusUrl).catch(() => null);
|
|
3443
|
+
if (current?.ok) {
|
|
3444
|
+
const status2 = await current.json().catch(() => null);
|
|
3445
|
+
const principal = String(status2?.lineage?.principal ?? "");
|
|
3446
|
+
const session = canonicalPrincipal(currentPrincipal() ?? "");
|
|
3447
|
+
if (await waitForWorkspaceMain(cloud, application) === void 0) {
|
|
3448
|
+
throw new Error(`application '${application}' is born but canonical ledger main did not become readable`);
|
|
3449
|
+
}
|
|
3450
|
+
return {
|
|
3451
|
+
application,
|
|
3452
|
+
parent: String(status2?.lineage?.parent ?? ""),
|
|
3453
|
+
principal,
|
|
3454
|
+
created: false,
|
|
3455
|
+
...principal !== "" && session !== "" && sameIdentity(principal, session) ? { deployPrincipal: principal } : {}
|
|
3456
|
+
};
|
|
3457
|
+
}
|
|
3458
|
+
if (current !== null && current.status !== 404 && current.status !== 409) {
|
|
3459
|
+
throw new Error(`could not inspect deploy target '${application}' (${current.status}); refusing to guess that it is unborn`);
|
|
3460
|
+
}
|
|
3461
|
+
const home = await ensureSovereignHome(opts);
|
|
3462
|
+
if (application === home.home) {
|
|
3463
|
+
return {
|
|
3464
|
+
application,
|
|
3465
|
+
parent: "root",
|
|
3466
|
+
principal: home.principal,
|
|
3467
|
+
created: home.created,
|
|
3468
|
+
deployPrincipal: home.principal
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
if (await fetch(statusUrl).then((r) => r.ok).catch(() => false)) {
|
|
3472
|
+
if (await waitForWorkspaceMain(cloud, application) === void 0) {
|
|
3473
|
+
throw new Error(`application '${application}' is born but canonical ledger main did not become readable`);
|
|
3474
|
+
}
|
|
3475
|
+
return {
|
|
3476
|
+
application,
|
|
3477
|
+
parent: home.home,
|
|
3478
|
+
principal: home.principal,
|
|
3479
|
+
created: false,
|
|
3480
|
+
deployPrincipal: home.principal
|
|
3481
|
+
};
|
|
3482
|
+
}
|
|
3483
|
+
const domains = await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home.home)}/domains`).then(async (r) => {
|
|
3484
|
+
if (!r.ok) throw new Error(`application parent law discovery failed (${r.status})`);
|
|
3485
|
+
return await r.json();
|
|
3486
|
+
});
|
|
3487
|
+
const frameworkHash = domains.currentLaw?.["nomos"];
|
|
3488
|
+
const lawHash = domains.currentLaw?.["workspaces"];
|
|
3489
|
+
if (!frameworkHash || !lawHash) {
|
|
3490
|
+
throw new Error(`the signed session home does not carry the framework law needed to birth '${application}'`);
|
|
3491
|
+
}
|
|
3492
|
+
const parent = await connectGovernance(cloud, home.home);
|
|
3493
|
+
const birthCert = await parent.certSign({
|
|
3494
|
+
child: application,
|
|
3495
|
+
founder: home.principal,
|
|
3496
|
+
verified: true,
|
|
3497
|
+
parentKey: home.device.public,
|
|
3498
|
+
parentId: home.home,
|
|
3499
|
+
epoch: 0,
|
|
3500
|
+
secret: home.device.secret
|
|
3501
|
+
});
|
|
3502
|
+
const bare = lineageIdentity(home.principal);
|
|
3503
|
+
const now = Date.now();
|
|
3504
|
+
const birth = await fetch(
|
|
3505
|
+
`${cloud}/v2/workspaces/${encodeURIComponent(home.home)}/workspaces/birthChild`,
|
|
3506
|
+
{
|
|
3507
|
+
method: "POST",
|
|
3508
|
+
headers: { "content-type": "application/json" },
|
|
3509
|
+
body: JSON.stringify({
|
|
3510
|
+
name: application,
|
|
3511
|
+
parent: home.home,
|
|
3512
|
+
principal: bare,
|
|
3513
|
+
tier: "edge",
|
|
3514
|
+
requestedBy: bare,
|
|
3515
|
+
requestedAt: now,
|
|
3516
|
+
foundingAdminHash: home.device.keyHash,
|
|
3517
|
+
bornAt: new Date(now).toISOString(),
|
|
3518
|
+
frameworkHash,
|
|
3519
|
+
lawHash,
|
|
3520
|
+
platformCert: JSON.stringify(birthCert),
|
|
3521
|
+
actor: home.principal,
|
|
3522
|
+
authorSecret: home.device.secret
|
|
3523
|
+
})
|
|
3524
|
+
}
|
|
3525
|
+
);
|
|
3526
|
+
const body = await birth.json().catch(() => null);
|
|
3527
|
+
const failed = body?.birthOutcomes?.find((outcome) => outcome.status !== "born");
|
|
3528
|
+
if (!birth.ok || body?.ok === false || failed) {
|
|
3529
|
+
if (!await fetch(statusUrl).then((r) => r.ok).catch(() => false)) {
|
|
3530
|
+
throw new Error(
|
|
3531
|
+
`Nomos could not create application '${application}' (${birth.status}): ${failed?.reason ?? String(body?.error ?? JSON.stringify(body))}`
|
|
3532
|
+
);
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
if (await waitForWorkspaceMain(cloud, application) === void 0) {
|
|
3536
|
+
throw new Error(`Nomos admitted application '${application}' but canonical ledger main did not become readable`);
|
|
3537
|
+
}
|
|
3538
|
+
const admin = await signAndPostOffer(
|
|
3539
|
+
application,
|
|
3540
|
+
"workspaces",
|
|
3541
|
+
"grantAdmin",
|
|
3542
|
+
{ principal: bare, label: "application founder", grantedBy: bare, grantedAt: now },
|
|
3543
|
+
{ ...opts, principal: bare }
|
|
3544
|
+
);
|
|
3545
|
+
if (!admin.ok) {
|
|
3546
|
+
throw new Error(`application '${application}' refused its founding admin (${admin.status}): ${JSON.stringify(admin.body)}`);
|
|
3547
|
+
}
|
|
3548
|
+
return {
|
|
3549
|
+
application,
|
|
3550
|
+
parent: home.home,
|
|
3551
|
+
principal: home.principal,
|
|
3552
|
+
created: true,
|
|
3553
|
+
deployPrincipal: home.principal
|
|
3554
|
+
};
|
|
3555
|
+
}
|
|
3424
3556
|
async function signAndPostWorkspaceRetirement(parent, workspaceId, creator, opts) {
|
|
3425
3557
|
return signAndPostPreparedOffer(
|
|
3426
3558
|
parent,
|
|
@@ -3438,12 +3570,15 @@ async function signAndPostChildLifecycle(parent, child, creator, action, opts) {
|
|
|
3438
3570
|
return signAndPostPreparedOffer(
|
|
3439
3571
|
parent,
|
|
3440
3572
|
void 0,
|
|
3441
|
-
(actor) =>
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3573
|
+
(actor) => {
|
|
3574
|
+
const creatorActing = creator !== "" && sameIdentity(creator, actor);
|
|
3575
|
+
return action === "retire" ? {
|
|
3576
|
+
directiveId: creatorActing ? "retireChild" : "retireChildAsAdmin",
|
|
3577
|
+
payload: { child, principal: creator, retiredBy: lineageIdentity(actor), retiredAt: Date.now() }
|
|
3578
|
+
} : {
|
|
3579
|
+
directiveId: creatorActing ? "reclaimChild" : "reclaimChildAsAdmin",
|
|
3580
|
+
payload: { child, reclaimedBy: lineageIdentity(actor), reclaimedAt: Date.now() }
|
|
3581
|
+
};
|
|
3447
3582
|
},
|
|
3448
3583
|
opts,
|
|
3449
3584
|
"self-if-unenrolled",
|
|
@@ -5627,6 +5762,22 @@ async function deploy2(ws, opts) {
|
|
|
5627
5762
|
return 1;
|
|
5628
5763
|
}
|
|
5629
5764
|
const fileName = file.split("/").pop();
|
|
5765
|
+
try {
|
|
5766
|
+
const { ensureApplicationWorkspace: ensureApplicationWorkspace2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
5767
|
+
const prepared = await ensureApplicationWorkspace2(ws, opts);
|
|
5768
|
+
if (prepared.deployPrincipal !== void 0 && opts.principal === void 0) {
|
|
5769
|
+
opts = {
|
|
5770
|
+
...opts,
|
|
5771
|
+
principal: prepared.deployPrincipal.startsWith("user:") ? prepared.deployPrincipal.slice("user:".length) : prepared.deployPrincipal
|
|
5772
|
+
};
|
|
5773
|
+
}
|
|
5774
|
+
if (prepared.created) {
|
|
5775
|
+
out4(` created application ${ws} under your Nomos home`);
|
|
5776
|
+
}
|
|
5777
|
+
} catch (e) {
|
|
5778
|
+
err4(`deploy '${ws}' could not prepare the application: ${e.message}`);
|
|
5779
|
+
return 1;
|
|
5780
|
+
}
|
|
5630
5781
|
const beforeLaw = await fetch(`${cloud}/v2/workspaces/${ws}/domains`).then((br) => br.json()).then((bd) => bd.ok === true ? bd : {}).catch(() => ({}));
|
|
5631
5782
|
const before = beforeLaw.domains ?? [];
|
|
5632
5783
|
const currentLaw2 = beforeLaw.currentLaw ?? {};
|
package/dist/dev-server.mjs
CHANGED
|
@@ -1846,32 +1846,42 @@ function aliasIdsFor(x, path2) {
|
|
|
1846
1846
|
return new Set(ids);
|
|
1847
1847
|
}
|
|
1848
1848
|
function resolveGatewayOperation(spec, opName, method) {
|
|
1849
|
-
if (!spec || !
|
|
1849
|
+
if (!spec || !opName || !method) return { op: null };
|
|
1850
|
+
const routeTables = [
|
|
1851
|
+
spec.paths ?? {},
|
|
1852
|
+
spec["x-nomos-framework-routes"]?.paths ?? {}
|
|
1853
|
+
];
|
|
1850
1854
|
const normalizedMethod = String(method).toLowerCase();
|
|
1851
1855
|
const exactPath = `/${String(opName).replace(/^\/+/, "")}`;
|
|
1852
|
-
const
|
|
1853
|
-
|
|
1856
|
+
for (const paths of routeTables) {
|
|
1857
|
+
const exact = paths[exactPath]?.[normalizedMethod];
|
|
1858
|
+
if (exact) return { op: exact, path: exactPath, ambiguous: null };
|
|
1859
|
+
}
|
|
1854
1860
|
const slash = String(opName).indexOf("/");
|
|
1855
1861
|
if (slash > 0) {
|
|
1856
1862
|
const requestedDomain = String(opName).slice(0, slash);
|
|
1857
1863
|
const requestedAlias = String(opName).slice(slash + 1);
|
|
1858
1864
|
const matches2 = [];
|
|
1859
|
-
for (const
|
|
1860
|
-
const
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1865
|
+
for (const paths of routeTables) {
|
|
1866
|
+
for (const [path2, methods] of Object.entries(paths)) {
|
|
1867
|
+
const op = methods?.[normalizedMethod];
|
|
1868
|
+
const x = op?.["x-nomos"];
|
|
1869
|
+
if (!op || !x || x.domain !== requestedDomain) continue;
|
|
1870
|
+
if (aliasIdsFor(x, path2).has(requestedAlias)) matches2.push({ op, path: path2 });
|
|
1871
|
+
}
|
|
1864
1872
|
}
|
|
1865
1873
|
if (matches2.length === 1) return { ...matches2[0], ambiguous: null };
|
|
1866
1874
|
if (matches2.length > 1) return { op: null, ambiguous: matches2.map((m) => m.path).sort() };
|
|
1867
1875
|
return { op: null, ambiguous: null };
|
|
1868
1876
|
}
|
|
1869
1877
|
const matches = [];
|
|
1870
|
-
for (const
|
|
1871
|
-
const
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1878
|
+
for (const paths of routeTables) {
|
|
1879
|
+
for (const [path2, methods] of Object.entries(paths)) {
|
|
1880
|
+
const op = methods?.[normalizedMethod];
|
|
1881
|
+
const x = op?.["x-nomos"];
|
|
1882
|
+
if (!op || !x) continue;
|
|
1883
|
+
if (aliasIdsFor(x, path2).has(opName)) matches.push({ op, path: path2 });
|
|
1884
|
+
}
|
|
1875
1885
|
}
|
|
1876
1886
|
if (matches.length === 1) return { ...matches[0], ambiguous: null };
|
|
1877
1887
|
if (matches.length > 1) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "githolon",
|
|
3
|
-
"version": "0.100.
|
|
3
|
+
"version": "0.100.5",
|
|
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.5",
|
|
33
|
+
"@githolon/dsl": "^0.100.5",
|
|
34
34
|
"isomorphic-git": "^1.38.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|