@githolon/dsl 0.24.0 → 0.24.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/package.json +1 -1
- package/src/codegen_proof.ts +117 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@githolon/dsl",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
package/src/codegen_proof.ts
CHANGED
|
@@ -361,6 +361,12 @@ export interface ChildBirthLeg {
|
|
|
361
361
|
readonly birthPayload: Record<string, unknown>;
|
|
362
362
|
/** Required `…At` fields the runtime stamps with ISO now() at dispatch (mirrors the create leg). */
|
|
363
363
|
readonly birthAutoStamped: readonly string[];
|
|
364
|
+
/** The payload field whose value is the authoring actor for this birth offer, when discoverable from the
|
|
365
|
+
* genesis recipe's step actors. Needed for gated births (`.births().requires(...)`) so proof drives the
|
|
366
|
+
* same actor the generated client would seal as `security.actor`. */
|
|
367
|
+
readonly birthActorField?: string;
|
|
368
|
+
/** The relation the birth offer requires (`.births().requires(...)`), when present. */
|
|
369
|
+
readonly birthRequiresRelation?: string;
|
|
364
370
|
/** The payload field that carries the bootstrap framework-controller hash (runtime: the local wasm's own
|
|
365
371
|
* controller hash) — discovered from the recipe's `bootstrap/installDomain` step's payload, by matching
|
|
366
372
|
* the field whose synthesized value the recipe routed there. `undefined` ⇒ the recipe hard-codes it. */
|
|
@@ -379,6 +385,21 @@ export interface ChildBirthLeg {
|
|
|
379
385
|
readonly childSeedInstanceId?: string;
|
|
380
386
|
/** A child declared query that reads the seed back (returns the seed aggregate). `undefined` ⇒ by-id only. */
|
|
381
387
|
readonly childQuery?: { readonly id: string; readonly key: readonly string[] };
|
|
388
|
+
/** Optional parent setup: when this birth is gated by authority that is established by first birthing the
|
|
389
|
+
* parent workspace (home → estate is the canonical case), the proof runner drives this setup birth first
|
|
390
|
+
* and then authors the child birth inside the born parent. */
|
|
391
|
+
readonly parentSetup?: ChildBirthParentSetup;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export interface ChildBirthParentSetup {
|
|
395
|
+
readonly parentDomain: string;
|
|
396
|
+
readonly birthDirectiveId: string;
|
|
397
|
+
readonly birthPayload: Record<string, unknown>;
|
|
398
|
+
readonly birthAutoStamped: readonly string[];
|
|
399
|
+
readonly birthActorField?: string;
|
|
400
|
+
readonly frameworkHashField?: string;
|
|
401
|
+
readonly lawHashField?: string;
|
|
402
|
+
readonly childDomain: string;
|
|
382
403
|
}
|
|
383
404
|
|
|
384
405
|
/** A stub `nomos` global (mint + sha256) so a `.births()` plan that mints / hashes a child name runs to
|
|
@@ -489,6 +510,19 @@ export function discoverChildBirthLeg(
|
|
|
489
510
|
const nomosStep = installSteps.find((s) => s.domain === "nomos");
|
|
490
511
|
const frameworkHashField = bootstrapStep ? fieldForValue(bootstrapStep.payload?.domainHash) : undefined;
|
|
491
512
|
const lawHashField = nomosStep ? fieldForValue(nomosStep.payload?.domainHash) : undefined;
|
|
513
|
+
const actorField = (() => {
|
|
514
|
+
for (const step of chain as Array<DiscoveredGenesisStep & { actor?: unknown }>) {
|
|
515
|
+
const actor = step?.actor;
|
|
516
|
+
const exact = fieldForValue(actor);
|
|
517
|
+
if (exact !== undefined) return exact;
|
|
518
|
+
if (typeof actor !== "string") continue;
|
|
519
|
+
for (const [field, value] of Object.entries(synth.value)) {
|
|
520
|
+
if (typeof value !== "string" || value.length === 0) continue;
|
|
521
|
+
if (actor === `user:${value}` || actor === `key:${value}`) return field;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return undefined;
|
|
525
|
+
})();
|
|
492
526
|
|
|
493
527
|
// The parent payload the leg dispatches: the synthesized values MINUS the framework/law-hash placeholders
|
|
494
528
|
// (the runtime injects the REAL hashes onto those fields by name — a `sample-*` hash would fail the child
|
|
@@ -502,6 +536,8 @@ export function discoverChildBirthLeg(
|
|
|
502
536
|
birthDirectiveId: birthDir.id,
|
|
503
537
|
birthPayload,
|
|
504
538
|
birthAutoStamped: synth.autoStamped,
|
|
539
|
+
...(actorField !== undefined ? { birthActorField: actorField } : {}),
|
|
540
|
+
...(birthDir.requiresRelationGate !== undefined ? { birthRequiresRelation: birthDir.requiresRelationGate.relation } : {}),
|
|
505
541
|
...(frameworkHashField !== undefined ? { frameworkHashField } : {}),
|
|
506
542
|
...(lawHashField !== undefined ? { lawHashField } : {}),
|
|
507
543
|
childDomain,
|
|
@@ -512,6 +548,38 @@ export function discoverChildBirthLeg(
|
|
|
512
548
|
};
|
|
513
549
|
}
|
|
514
550
|
|
|
551
|
+
function childBirthsForModule(mod: DomainModule, modules: readonly DomainModule[]): ChildBirthLeg[] {
|
|
552
|
+
const domain = mod.domain ?? mod.name;
|
|
553
|
+
const out: ChildBirthLeg[] = [];
|
|
554
|
+
for (const d of mod.directives as Directive<unknown>[]) {
|
|
555
|
+
if (d?.birthsChild !== true || typeof d.payloadSchema !== "object") continue;
|
|
556
|
+
const leg = discoverChildBirthLeg(d, domain, modules);
|
|
557
|
+
if (leg !== undefined) out.push(leg);
|
|
558
|
+
}
|
|
559
|
+
return out;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function asParentSetup(leg: ChildBirthLeg): ChildBirthParentSetup {
|
|
563
|
+
return {
|
|
564
|
+
parentDomain: leg.parentDomain,
|
|
565
|
+
birthDirectiveId: leg.birthDirectiveId,
|
|
566
|
+
birthPayload: leg.birthPayload,
|
|
567
|
+
birthAutoStamped: leg.birthAutoStamped,
|
|
568
|
+
...(leg.birthActorField !== undefined ? { birthActorField: leg.birthActorField } : {}),
|
|
569
|
+
...(leg.frameworkHashField !== undefined ? { frameworkHashField: leg.frameworkHashField } : {}),
|
|
570
|
+
...(leg.lawHashField !== undefined ? { lawHashField: leg.lawHashField } : {}),
|
|
571
|
+
childDomain: leg.childDomain,
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function attachParentSetup(leg: ChildBirthLeg, allBirths: readonly ChildBirthLeg[]): ChildBirthLeg {
|
|
576
|
+
if (leg.birthRequiresRelation === undefined) return leg;
|
|
577
|
+
const setup = allBirths.find((candidate) =>
|
|
578
|
+
candidate.childDomain === leg.parentDomain &&
|
|
579
|
+
!(candidate.parentDomain === leg.parentDomain && candidate.birthDirectiveId === leg.birthDirectiveId));
|
|
580
|
+
return setup === undefined ? leg : { ...leg, parentSetup: asParentSetup(setup) };
|
|
581
|
+
}
|
|
582
|
+
|
|
515
583
|
/** Discover the SINGLETON instance id a seed directive writes (a fixed `<Agg>:self`-shaped id), by running
|
|
516
584
|
* its plan with a probe payload + birth-probe globals and reading the first written op's instance id when
|
|
517
585
|
* it is a constant (the same id across two distinct probe payloads). `undefined` ⇒ not a fixed singleton. */
|
|
@@ -644,6 +712,7 @@ function birthDirectiveOf(mod: DomainModule): Directive<unknown> | undefined {
|
|
|
644
712
|
* domain is at least `compile-valid` (gaps 1+3 — every domain is proof-addressable). */
|
|
645
713
|
export function legsForDomain(mod: DomainModule, modules: readonly DomainModule[]): ProofLegs {
|
|
646
714
|
const domain = mod.domain ?? mod.name;
|
|
715
|
+
const allBirths = modules.flatMap((m) => childBirthsForModule(m, modules));
|
|
647
716
|
// The standalone-create leg (when the domain has a non-birth `.creates`). FAIL SOFT: an exotic payload
|
|
648
717
|
// shape the synthesizer can't sample just drops the standalone leg (the domain stays compile-valid /
|
|
649
718
|
// child-birth-provable), never loses the index.
|
|
@@ -655,11 +724,12 @@ export function legsForDomain(mod: DomainModule, modules: readonly DomainModule[
|
|
|
655
724
|
}
|
|
656
725
|
// The child-birth leg (when the domain has a `.births()` directive) — discovered by running its plan.
|
|
657
726
|
const birthDir = birthDirectiveOf(mod);
|
|
658
|
-
const childBirth = birthDir !== undefined ?
|
|
727
|
+
const childBirth = birthDir !== undefined ? allBirths.find((b) => b.parentDomain === domain && b.birthDirectiveId === birthDir.id) : undefined;
|
|
728
|
+
const childBirthWithSetup = childBirth !== undefined ? attachParentSetup(childBirth, allBirths) : undefined;
|
|
659
729
|
|
|
660
730
|
const legs: ProofKind[] = ["compile-valid"];
|
|
661
731
|
if (standalone !== null) legs.push("standalone-provable");
|
|
662
|
-
if (
|
|
732
|
+
if (childBirthWithSetup !== undefined) legs.push("child-birth-provable");
|
|
663
733
|
|
|
664
734
|
return {
|
|
665
735
|
domain,
|
|
@@ -675,7 +745,7 @@ export function legsForDomain(mod: DomainModule, modules: readonly DomainModule[
|
|
|
675
745
|
...(standalone.count !== undefined ? { count: standalone.count } : {}),
|
|
676
746
|
}
|
|
677
747
|
: {}),
|
|
678
|
-
...(
|
|
748
|
+
...(childBirthWithSetup !== undefined ? { childBirth: childBirthWithSetup } : {}),
|
|
679
749
|
};
|
|
680
750
|
}
|
|
681
751
|
|
|
@@ -798,26 +868,65 @@ function liveChildBirthLegLines(cb: ChildBirthLeg, opts: TsProofOptions, n: () =
|
|
|
798
868
|
// The birth payload literal: the synthesized values + the REAL hashes onto the discovered fields + the
|
|
799
869
|
// auto-stamped `…At` fields stamped now.
|
|
800
870
|
const lines: string[] = [];
|
|
871
|
+
const setup = cb.parentSetup;
|
|
872
|
+
const actorExpr = (field: string | undefined, payloadVar: string): string | undefined =>
|
|
873
|
+
field !== undefined ? `String(${payloadVar}[${JSON.stringify(field)}] ?? "")` : undefined;
|
|
874
|
+
const birthActorExpr = actorExpr(cb.birthActorField, "birthPayload");
|
|
801
875
|
lines.push(
|
|
802
876
|
`// ${n()}. CHILD BIRTH (G3 — birth is the defined consequence of an offer): drive \`${cb.parentDomain}/${cb.birthDirectiveId}\``,
|
|
803
877
|
`// against the cloud; the kernel's offer-effect installs the child law in-chain + folds the child's`,
|
|
804
878
|
`// genesis (estate/${cb.childSeedDirectiveId}) through the CHILD's own gate, then BORNS the child workspace.`,
|
|
805
879
|
`{`,
|
|
880
|
+
` const frameworkHashFor = async (workspace: string) => {`,
|
|
881
|
+
` const st = await (await fetch(\`\${CLOUD}/v2/workspaces/\${workspace}\`)).json().catch(() => ({}));`,
|
|
882
|
+
` const frameworkHash = st.controller?.domainHash ?? st.controllerHash ?? "";`,
|
|
883
|
+
` if (!frameworkHash) fail(\`could not resolve the framework controller hash from workspace \${workspace} — needed for the child's in-chain installDomain\`);`,
|
|
884
|
+
` return frameworkHash;`,
|
|
885
|
+
` };`,
|
|
806
886
|
` const birthPayload: Record<string, unknown> = { ...${JSON.stringify(cb.birthPayload)} };`,
|
|
887
|
+
...(
|
|
888
|
+
birthActorExpr !== undefined && cb.birthRequiresRelation !== undefined
|
|
889
|
+
? [
|
|
890
|
+
` const birthActor = ${birthActorExpr};`,
|
|
891
|
+
` if (!birthActor) fail(${JSON.stringify(`child birth ${cb.parentDomain}/${cb.birthDirectiveId} is gated by .requires("${cb.birthRequiresRelation}") but the proof could not derive an actor from ${cb.birthActorField}`)});`,
|
|
892
|
+
]
|
|
893
|
+
: [
|
|
894
|
+
` const birthActor = PRINCIPAL;`,
|
|
895
|
+
]
|
|
896
|
+
),
|
|
897
|
+
...(setup !== undefined
|
|
898
|
+
? [
|
|
899
|
+
` // Parent setup: this child birth is gated by authority seeded when the parent workspace is born.`,
|
|
900
|
+
` const setupPayload: Record<string, unknown> = { ...${JSON.stringify(setup.birthPayload)} };`,
|
|
901
|
+
...(setup.birthActorField !== undefined && cb.birthActorField !== undefined
|
|
902
|
+
? [` setupPayload[${JSON.stringify(setup.birthActorField)}] = birthPayload[${JSON.stringify(cb.birthActorField)}];`]
|
|
903
|
+
: []),
|
|
904
|
+
...(setup.frameworkHashField !== undefined ? [` setupPayload[${JSON.stringify(setup.frameworkHashField)}] = await frameworkHashFor(WS);`] : []),
|
|
905
|
+
...(setup.lawHashField !== undefined ? [` setupPayload[${JSON.stringify(setup.lawHashField)}] = ${hashConst};`] : []),
|
|
906
|
+
...setup.birthAutoStamped.map((f) => ` setupPayload[${JSON.stringify(f)}] = new Date().toISOString();`),
|
|
907
|
+
` const setupActor = ${actorExpr(setup.birthActorField, "setupPayload") ?? "birthActor"} || birthActor;`,
|
|
908
|
+
` const sr = await fetch(\`\${CLOUD}/v2/workspaces/\${WS}/${setup.birthDirectiveId}\`, { method: "POST", headers: { "content-type": "application/json", "x-nomos-principal": setupActor }, body: JSON.stringify(setupPayload) });`,
|
|
909
|
+
` const sd = await sr.json();`,
|
|
910
|
+
` if (!sd.ok) fail(\`parent setup ${setup.parentDomain}/${setup.birthDirectiveId} refused: \${JSON.stringify(sd)}\`);`,
|
|
911
|
+
` const setupBorn: Array<{ workspace?: string }> = sd.born ?? [];`,
|
|
912
|
+
` const birthParentWs = setupBorn[0]?.workspace;`,
|
|
913
|
+
` if (!birthParentWs) fail(\`parent setup admitted but spawned no workspace (born=\${JSON.stringify(setupBorn)})\`);`,
|
|
914
|
+
` ok(\`parent setup — \${birthParentWs} born by ${setup.parentDomain}/${setup.birthDirectiveId} before gated child birth\`);`,
|
|
915
|
+
]
|
|
916
|
+
: [
|
|
917
|
+
` const birthParentWs = WS;`,
|
|
918
|
+
]),
|
|
807
919
|
...(cb.frameworkHashField !== undefined
|
|
808
920
|
? [
|
|
809
921
|
` // The framework CONTROLLER hash (the bootstrap install-target the child runs as intent 0) — read it`,
|
|
810
922
|
` // from the workspace's own status (the kernel's controllerHash); the child install resolves the bytes`,
|
|
811
923
|
` // by hash from the parent's custody, so this MUST be the real framework hash (a guess would fail).`,
|
|
812
|
-
`
|
|
813
|
-
` const frameworkHash = st.controller?.domainHash ?? st.controllerHash ?? "";`,
|
|
814
|
-
` if (!frameworkHash) fail("could not resolve the framework controller hash from the workspace status — needed for the child's in-chain installDomain");`,
|
|
815
|
-
` birthPayload[${JSON.stringify(cb.frameworkHashField)}] = frameworkHash;`,
|
|
924
|
+
` birthPayload[${JSON.stringify(cb.frameworkHashField)}] = await frameworkHashFor(birthParentWs);`,
|
|
816
925
|
]
|
|
817
926
|
: []),
|
|
818
927
|
` birthPayload[${JSON.stringify(cb.lawHashField ?? "lawHash")}] = ${hashConst};`,
|
|
819
928
|
...cb.birthAutoStamped.map((f) => ` birthPayload[${JSON.stringify(f)}] = new Date().toISOString();`),
|
|
820
|
-
` const br = await fetch(\`\${CLOUD}/v2/workspaces/\${
|
|
929
|
+
` const br = await fetch(\`\${CLOUD}/v2/workspaces/\${birthParentWs}/${cb.birthDirectiveId}\`, { method: "POST", headers: { "content-type": "application/json", "x-nomos-principal": birthActor }, body: JSON.stringify(birthPayload) });`,
|
|
821
930
|
` const bd = await br.json();`,
|
|
822
931
|
` if (!bd.ok) fail(\`child birth offer ${cb.parentDomain}/${cb.birthDirectiveId} refused: \${JSON.stringify(bd)}\`);`,
|
|
823
932
|
` const born: Array<{ workspace?: string }> = bd.born ?? [];`,
|