@githolon/dsl 0.60.1 → 0.61.0
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/directive.ts +30 -0
- package/src/framework/era_certification.ts +79 -0
- package/src/usd.ts +21 -0
- package/src/usd_layers.ts +16 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@githolon/dsl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
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/directive.ts
CHANGED
|
@@ -163,6 +163,18 @@ export interface Directive<P = unknown> {
|
|
|
163
163
|
/** The payload field holding the claimed issuer (the gate asserts it == the prefix AuthProvider.issuer). */
|
|
164
164
|
readonly verifiedViaField: string;
|
|
165
165
|
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* THE LAWFUL-RECOVERY GATE (architecture/lawful_recovery.md). Present IFF this directive declares
|
|
169
|
+
* `.certifiesEra()`: it is the CUSTODIAN-authored `certifyEra` verb. Lowered into the `nomosEraCertGate`
|
|
170
|
+
* USD era key (the directive id + the payload field carrying the signed `EraCertification`), so the kernel
|
|
171
|
+
* admits this intent by verifying its author against the pinned `K_root` via the carried certification —
|
|
172
|
+
* NOT the workspace signer roster — and the walk waives the identity attestation for the oids it covers.
|
|
173
|
+
* The kernel hardcodes NEITHER; it reads both from this declaration. Framework `certifyEra` default field.
|
|
174
|
+
*/
|
|
175
|
+
readonly certifiesEraGate?: {
|
|
176
|
+
readonly certField: string;
|
|
177
|
+
};
|
|
166
178
|
/**
|
|
167
179
|
* The directive's DECLARED read boundary: the ref types its `plan` may READ (the
|
|
168
180
|
* "IR for law boundaries" decision — the boundary is part of the domain identity).
|
|
@@ -318,6 +330,14 @@ export interface RequirableDirective<P> extends Directive<P> {
|
|
|
318
330
|
keyHashField?: string;
|
|
319
331
|
verifiedViaField?: string;
|
|
320
332
|
}): RequirableDirective<P>;
|
|
333
|
+
/**
|
|
334
|
+
* Declare this directive the CUSTODIAN-authored `certifyEra` recovery verb (architecture/lawful_recovery.md).
|
|
335
|
+
* Its author is verified to the pinned `K_root` via the carried [`EraCertification`] (NOT the workspace
|
|
336
|
+
* signer roster), and the kernel walk WAIVES the identity attestation for the oids the certification covers
|
|
337
|
+
* (the law/plan gate stays enforced). Emits the `nomosEraCertGate` era key naming this directive + the
|
|
338
|
+
* payload field holding the artifact (default `certification`). Returns a NEW requirable directive.
|
|
339
|
+
*/
|
|
340
|
+
certifiesEra(opts?: { certField?: string }): RequirableDirective<P>;
|
|
321
341
|
/**
|
|
322
342
|
* Declare the directive's READ boundary. TWO argument kinds, one declaration site:
|
|
323
343
|
* * a STRING declares a ref TYPE its `plan` may read (the original boundary —
|
|
@@ -679,6 +699,16 @@ function makeRequirable<P>(base: Directive<P>): RequirableDirective<P> {
|
|
|
679
699
|
},
|
|
680
700
|
});
|
|
681
701
|
},
|
|
702
|
+
certifiesEra(opts?: { certField?: string }): RequirableDirective<P> {
|
|
703
|
+
// LAWFUL RECOVERY: this directive is the custodian-authored `certifyEra` verb. Lower its id + the
|
|
704
|
+
// payload field carrying the signed `EraCertification` into the `nomosEraCertGate` era key — the kernel
|
|
705
|
+
// reads both from the law (hardcoding neither) to admit the intent (author verified to K_root) + waive
|
|
706
|
+
// the identity attestation for the certified oids. Default field HERE (the framework convention).
|
|
707
|
+
return makeRequirable({
|
|
708
|
+
...base,
|
|
709
|
+
certifiesEraGate: { certField: opts?.certField ?? "certification" },
|
|
710
|
+
});
|
|
711
|
+
},
|
|
682
712
|
reads(...reads: (string | QueryDecl)[]): RequirableDirective<P> {
|
|
683
713
|
// Split by argument kind: strings are the ref-type boundary; QueryDecls are the
|
|
684
714
|
// captured-read lane (#58). Both accumulate, dedup (ref types by value, queries
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// NOMOS — LAWFUL RECOVERY (architecture/lawful_recovery.md). The `certifyEra` verb, shipped in the `nomos`
|
|
2
|
+
// CONTROLLER domain (installed in EVERY workspace via bootstrap/installDomain) so ANY chain can fold a
|
|
3
|
+
// custodian's recovery fact. A CUSTODIAN (root operator / a platform over its subtree) folds a SIGNED,
|
|
4
|
+
// in-chain `EraCertification` that WAIVES the IDENTITY ATTESTATION for a named set of intent oids — while
|
|
5
|
+
// the law/plan gate stays fully enforced. A custodian may VOUCH IDENTITY (heal a ForgedPrincipal/BadSignature
|
|
6
|
+
// scar left by a lost enrollment or a compaction), never authorize an unlawful write.
|
|
7
|
+
//
|
|
8
|
+
// THE CRYPTO LIVES IN THE KERNEL: `.certifiesEra()` emits the `nomosEraCertGate` era key (this directive id +
|
|
9
|
+
// the payload field carrying the artifact). The kernel then (a) ADMITS this intent by verifying its author
|
|
10
|
+
// against the pinned `K_root` via the carried certification — NOT the workspace signer roster, since the
|
|
11
|
+
// custodian is not enrolled here — and (b) in verify_chain, pre-scans the timeline for certifications and
|
|
12
|
+
// WAIVES the identity attestation for the oids they cover. The DSL plan only FOLDS the fact (audit surface);
|
|
13
|
+
// the plan CANNOT and does not verify the signature — that is the kernel's, on every lane.
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import { aggregate, instance } from "../aggregate.js";
|
|
16
|
+
import { Lww } from "../drivers.js";
|
|
17
|
+
import { t } from "../fields.js";
|
|
18
|
+
import { directive } from "../directive.js";
|
|
19
|
+
import { set, type PlannedOp } from "../ops.js";
|
|
20
|
+
import { query } from "../query.js";
|
|
21
|
+
|
|
22
|
+
/** THE FOLDED RECOVERY FACT — one per certification, content-addressed (`era-certification:<id>`), append-
|
|
23
|
+
* only. The `certification` field holds the exact signed artifact JSON the kernel verified; the flat fields
|
|
24
|
+
* make it queryable (who certified what, when, why). NOT truth about the waiver — the kernel's verify is —
|
|
25
|
+
* just the AUDIT record that a custodian acted, and its attribution. */
|
|
26
|
+
export const EraCertification = aggregate("EraCertification", {
|
|
27
|
+
/** The signed artifact JSON verbatim (workspaceId, intentOids, waives, reason, custodianKey, signature,
|
|
28
|
+
* certChain) — the exact bytes the kernel's `era_cert::verify` checked against K_root + this chain. */
|
|
29
|
+
certification: t.string().merge(Lww),
|
|
30
|
+
/** The custodian's public key (base64) — WHO vouched (audit; the kernel proved it roots at K_root). */
|
|
31
|
+
custodianKey: t.string().merge(Lww),
|
|
32
|
+
/** The operator's mandatory justification (audit). */
|
|
33
|
+
reason: t.string().merge(Lww),
|
|
34
|
+
/** The custodian's HLC at issue (audit). */
|
|
35
|
+
certifiedAt: t.string().merge(Lww),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const eraCertPayload = z.object({
|
|
39
|
+
/** The content-addressed id for the folded fact (`sha256(canonical artifact)` — caller-computed). */
|
|
40
|
+
certId: z.string().min(1),
|
|
41
|
+
/** The signed `EraCertification` artifact (the kernel verifies it against K_root + this chain's self-id). */
|
|
42
|
+
certification: z.string().min(1),
|
|
43
|
+
/** The custodian public key (base64) — audit; the kernel derives authority from the artifact's certChain. */
|
|
44
|
+
custodianKey: z.string().min(1),
|
|
45
|
+
/** The mandatory operator justification. */
|
|
46
|
+
reason: z.string().min(1),
|
|
47
|
+
/** ISO-8601, caller-stamped (the timestamp doctrine — the plan reads no clock). */
|
|
48
|
+
certifiedAt: z.string().min(1),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* `certifyEra` — THE LAWFUL OPERATOR RECOVERY VERB. A custodian offers this against the SCARRED workspace;
|
|
53
|
+
* the kernel admits it by verifying the carried certification's author to the pinned `K_root` (root operator
|
|
54
|
+
* = a certification signed directly by K_root; a platform custodian = a certChain to K_root, scoped to its
|
|
55
|
+
* subtree). The plan folds the audit fact; the kernel's verify_chain pre-scan reads the SAME certification
|
|
56
|
+
* from this intent's payload and WAIVES the identity attestation for the oids it names. `.requires` NOTHING:
|
|
57
|
+
* authorization is the K_root-rooted signature (the whole point — the custodian is not an enrolled signer of
|
|
58
|
+
* the child), enforced by the era gate, not a relation.
|
|
59
|
+
*/
|
|
60
|
+
export const certifyEra = directive("certifyEra")
|
|
61
|
+
.ensures(EraCertification)
|
|
62
|
+
.payload(eraCertPayload)
|
|
63
|
+
.plan((p): PlannedOp[] => {
|
|
64
|
+
const fact = instance(EraCertification, `era-certification:${p.certId}`);
|
|
65
|
+
return [
|
|
66
|
+
set(fact, "certification", p.certification),
|
|
67
|
+
set(fact, "custodianKey", p.custodianKey),
|
|
68
|
+
set(fact, "reason", p.reason),
|
|
69
|
+
set(fact, "certifiedAt", p.certifiedAt),
|
|
70
|
+
];
|
|
71
|
+
})
|
|
72
|
+
// Emit the `nomosEraCertGate` era key (this directive id + the `certification` payload field). The kernel
|
|
73
|
+
// reads both from the law, admitting the intent (author verified to K_root) + waiving the certified oids.
|
|
74
|
+
.certifiesEra();
|
|
75
|
+
|
|
76
|
+
/** Read the folded certifications by custodian (audit / `githolon gov certifications`). */
|
|
77
|
+
export const eraCertificationsByCustodian = query("eraCertificationsByCustodian")
|
|
78
|
+
.key("custodianKey")
|
|
79
|
+
.returns(EraCertification);
|
package/src/usd.ts
CHANGED
|
@@ -348,6 +348,18 @@ export interface UsdLayer {
|
|
|
348
348
|
}
|
|
349
349
|
>;
|
|
350
350
|
};
|
|
351
|
+
/**
|
|
352
|
+
* THE LAWFUL-RECOVERY GATE (architecture/lawful_recovery.md). Present IFF a directive declares
|
|
353
|
+
* `.certifiesEra()`: names that directive id + the payload field carrying the signed `EraCertification`.
|
|
354
|
+
* The kernel's `nomosEraCertGate` arm admits the custodian-authored intent (verified to `K_root` via the
|
|
355
|
+
* certification, not the signer roster) + the walk waives the identity attestation for the certified oids.
|
|
356
|
+
* OMITTED for law with no certifyEra directive (the era rule — byte-identical hash; the arm inert).
|
|
357
|
+
*/
|
|
358
|
+
readonly nomosEraCertGate?: {
|
|
359
|
+
readonly v: 1;
|
|
360
|
+
readonly directiveId: string;
|
|
361
|
+
readonly certField: string;
|
|
362
|
+
};
|
|
351
363
|
/**
|
|
352
364
|
* THE BIRTH GATE DECLARATION (G3 — birth is a declared kernel primitive, the unix model). Present IFF ≥1
|
|
353
365
|
* directive declares `.births()`: the SORTED set of their ids. A directive named here BIRTHS a child
|
|
@@ -1204,6 +1216,14 @@ export function emitUsd(
|
|
|
1204
1216
|
}
|
|
1205
1217
|
const nomosVerifiedFirstEnroll =
|
|
1206
1218
|
Object.keys(firstEnrollReq).length > 0 ? { v: 1 as const, directives: firstEnrollReq } : undefined;
|
|
1219
|
+
// LAWFUL RECOVERY: the sole `.certifiesEra()` directive (if any) → the `nomosEraCertGate` era key.
|
|
1220
|
+
// (One certifyEra verb per controller law; the last declared wins — the framework declares exactly one.)
|
|
1221
|
+
let eraCertGate: UsdLayer["nomosEraCertGate"];
|
|
1222
|
+
for (const d of [...l.module.directives].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))) {
|
|
1223
|
+
if (d.certifiesEraGate !== undefined) {
|
|
1224
|
+
eraCertGate = { v: 1 as const, directiveId: d.id, certField: d.certifiesEraGate.certField };
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1207
1227
|
// THE CAPTURED-READ GATE DECLARATION (#58): collected from the canonical
|
|
1208
1228
|
// manifest's per-directive `capturedReads` (omit-when-empty — read-free law's
|
|
1209
1229
|
// USD is byte-identical apart from the always-on stableIds key).
|
|
@@ -1358,6 +1378,7 @@ export function emitUsd(
|
|
|
1358
1378
|
...(nomosBirthRecordGate !== undefined ? { nomosBirthRecordGate } : {}),
|
|
1359
1379
|
...(nomosParentAttestedBirth !== undefined ? { nomosParentAttestedBirth } : {}),
|
|
1360
1380
|
...(nomosVerifiedFirstEnroll !== undefined ? { nomosVerifiedFirstEnroll } : {}),
|
|
1381
|
+
...(eraCertGate !== undefined ? { nomosEraCertGate: eraCertGate } : {}),
|
|
1361
1382
|
...(nomosValueObjects !== undefined ? { nomosValueObjects } : {}),
|
|
1362
1383
|
...(Object.keys(visAggregates).length > 0
|
|
1363
1384
|
? { nomosReadVisibility: { v: 1 as const, aggregates: visAggregates } }
|
package/src/usd_layers.ts
CHANGED
|
@@ -200,6 +200,9 @@ function domainLayerAttrLines(domain: string, layer: UsdLayer, indent: string):
|
|
|
200
200
|
...(layer.nomosVerifiedFirstEnroll !== undefined
|
|
201
201
|
? [`${indent}custom string nomos:verifiedFirstEnrollHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosVerifiedFirstEnroll)))}`]
|
|
202
202
|
: []),
|
|
203
|
+
...(layer.nomosEraCertGate !== undefined
|
|
204
|
+
? [`${indent}custom string nomos:eraCertGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosEraCertGate)))}`]
|
|
205
|
+
: []),
|
|
203
206
|
...(layer.nomosValueObjects !== undefined
|
|
204
207
|
? [`${indent}custom string nomos:valueObjectsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosValueObjects)))}`]
|
|
205
208
|
: []),
|
|
@@ -910,6 +913,11 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
910
913
|
verifiedFirstEnroll = { v: 1, directives: rec };
|
|
911
914
|
}
|
|
912
915
|
}
|
|
916
|
+
// LAWFUL RECOVERY: the single `nomosEraCertGate` (later-wins across the stack — one certifyEra verb).
|
|
917
|
+
let eraCertGate: UsdLayer["nomosEraCertGate"];
|
|
918
|
+
for (const l of stack) {
|
|
919
|
+
if (l.nomosEraCertGate !== undefined) eraCertGate = l.nomosEraCertGate;
|
|
920
|
+
}
|
|
913
921
|
// FIRST-CLASS VALUE OBJECTS (+ the VO↔field usage pointers): descriptors merged
|
|
914
922
|
// later-wins per NAME, usages later-wins per (aggregate, field), both SORTED —
|
|
915
923
|
// so the layered fold stays byte-homomorphic with `emitUsd`'s composed emission.
|
|
@@ -956,6 +964,7 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
956
964
|
...(birthRecordGate !== undefined ? { nomosBirthRecordGate: birthRecordGate } : {}),
|
|
957
965
|
...(parentAttestedBirth !== undefined ? { nomosParentAttestedBirth: parentAttestedBirth } : {}),
|
|
958
966
|
...(verifiedFirstEnroll !== undefined ? { nomosVerifiedFirstEnroll: verifiedFirstEnroll } : {}),
|
|
967
|
+
...(eraCertGate !== undefined ? { nomosEraCertGate: eraCertGate } : {}),
|
|
959
968
|
...(valueObjects !== undefined ? { nomosValueObjects: valueObjects } : {}),
|
|
960
969
|
};
|
|
961
970
|
});
|
|
@@ -1094,6 +1103,7 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
1094
1103
|
const birthRecordGateByDomain = new Map<string, UsdLayer["nomosBirthRecordGate"]>();
|
|
1095
1104
|
const parentAttestedBirthByDomain = new Map<string, UsdLayer["nomosParentAttestedBirth"]>();
|
|
1096
1105
|
const verifiedFirstEnrollByDomain = new Map<string, UsdLayer["nomosVerifiedFirstEnroll"]>();
|
|
1106
|
+
const eraCertGateByDomain = new Map<string, UsdLayer["nomosEraCertGate"]>();
|
|
1097
1107
|
const valueObjectsByDomain = new Map<string, UsdLayer["nomosValueObjects"]>();
|
|
1098
1108
|
for (const p of prims) {
|
|
1099
1109
|
if (p.attrs.get("nomos:kind") === "domain") {
|
|
@@ -1181,6 +1191,10 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
1181
1191
|
if (typeof vfeHex === "string") {
|
|
1182
1192
|
verifiedFirstEnrollByDomain.set(domain, JSON.parse(unhexUtf8(vfeHex)) as UsdLayer["nomosVerifiedFirstEnroll"]);
|
|
1183
1193
|
}
|
|
1194
|
+
const ecgHex = p.attrs.get("nomos:eraCertGateHex");
|
|
1195
|
+
if (typeof ecgHex === "string") {
|
|
1196
|
+
eraCertGateByDomain.set(domain, JSON.parse(unhexUtf8(ecgHex)) as UsdLayer["nomosEraCertGate"]);
|
|
1197
|
+
}
|
|
1184
1198
|
// FIRST-CLASS VALUE OBJECTS: the hex-carried descriptor set (descriptive, not a gate).
|
|
1185
1199
|
const voHex = p.attrs.get("nomos:valueObjectsHex");
|
|
1186
1200
|
if (typeof voHex === "string") {
|
|
@@ -1290,6 +1304,7 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
1290
1304
|
const birthRecordGate = birthRecordGateByDomain.get(domain);
|
|
1291
1305
|
const parentAttestedBirth = parentAttestedBirthByDomain.get(domain);
|
|
1292
1306
|
const verifiedFirstEnroll = verifiedFirstEnrollByDomain.get(domain);
|
|
1307
|
+
const eraCertGate = eraCertGateByDomain.get(domain);
|
|
1293
1308
|
const valueObjects = valueObjectsByDomain.get(domain);
|
|
1294
1309
|
return {
|
|
1295
1310
|
path: `/Nomos/${domain}`,
|
|
@@ -1314,6 +1329,7 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
1314
1329
|
...(birthRecordGate !== undefined ? { nomosBirthRecordGate: birthRecordGate } : {}),
|
|
1315
1330
|
...(parentAttestedBirth !== undefined ? { nomosParentAttestedBirth: parentAttestedBirth } : {}),
|
|
1316
1331
|
...(verifiedFirstEnroll !== undefined ? { nomosVerifiedFirstEnroll: verifiedFirstEnroll } : {}),
|
|
1332
|
+
...(eraCertGate !== undefined ? { nomosEraCertGate: eraCertGate } : {}),
|
|
1317
1333
|
...(valueObjects !== undefined ? { nomosValueObjects: valueObjects } : {}),
|
|
1318
1334
|
};
|
|
1319
1335
|
})
|