@githolon/dsl 0.5.1 → 0.7.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/aggregate.ts +168 -4
- package/src/authoring.ts +18 -6
- package/src/build_package.ts +10 -1
- package/src/codegen_dart.ts +10 -0
- package/src/codegen_ts.ts +2 -0
- package/src/drivers.ts +48 -2
- package/src/engine_entry.ts +7 -0
- package/src/fields.ts +46 -0
- package/src/framework/encryption_identity.ts +92 -0
- package/src/framework/encryption_scope.ts +158 -0
- package/src/framework/relations.ts +205 -0
- package/src/framework/workspaces.ts +41 -2
- package/src/index.ts +47 -1
- package/src/manifest.ts +54 -2
- package/src/usd.ts +50 -0
- package/src/usd_layers.ts +68 -3
- package/src/wire.ts +7 -3
package/src/usd_layers.ts
CHANGED
|
@@ -99,12 +99,14 @@ export function usdaStringArray(items: readonly string[]): string {
|
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
101
|
* A `WireDriver` as a READABLE usda token: unit drivers are their bare serde
|
|
102
|
-
* string (`"Lww"`, `"AddWins"`, …); `MapOf` nests as `MapOf(<inner>)
|
|
103
|
-
*
|
|
104
|
-
*
|
|
102
|
+
* string (`"Lww"`, `"AddWins"`, `"LwwCausal"`, …); `MapOf` nests as `MapOf(<inner>)`;
|
|
103
|
+
* the EXPLICIT TIME-AUTHORITY `LwwBy` carries its principal as `LwwBy(<principal>)`.
|
|
104
|
+
* Readable on purpose — the usdcat/usdview tree is the visual proof, so the merge law
|
|
105
|
+
* (and the time-authority) of every field must be legible in it (hex would bury the point).
|
|
105
106
|
*/
|
|
106
107
|
export function driverToken(driver: WireDriver): string {
|
|
107
108
|
if (typeof driver === "string") return driver;
|
|
109
|
+
if ("LwwBy" in driver) return `LwwBy(${driver.LwwBy})`;
|
|
108
110
|
return `MapOf(${driverToken(driver.MapOf)})`;
|
|
109
111
|
}
|
|
110
112
|
|
|
@@ -113,6 +115,15 @@ export function parseDriverToken(token: string): WireDriver {
|
|
|
113
115
|
if (token.startsWith("MapOf(") && token.endsWith(")")) {
|
|
114
116
|
return { MapOf: parseDriverToken(token.slice("MapOf(".length, -1)) };
|
|
115
117
|
}
|
|
118
|
+
// `LwwBy(<principal>)` — the principal is an opaque non-empty string (uids carry
|
|
119
|
+
// hyphens, so it is NOT the bare-identifier shape the unit-driver branch validates).
|
|
120
|
+
if (token.startsWith("LwwBy(") && token.endsWith(")")) {
|
|
121
|
+
const principal = token.slice("LwwBy(".length, -1);
|
|
122
|
+
if (principal.length === 0) {
|
|
123
|
+
throw new Error(`usd-layers: LwwBy driver token names no time-authority principal`);
|
|
124
|
+
}
|
|
125
|
+
return { LwwBy: principal };
|
|
126
|
+
}
|
|
116
127
|
if (!/^[A-Za-z][A-Za-z0-9]*$/.test(token)) {
|
|
117
128
|
throw new Error(`usd-layers: malformed driver token '${token}'`);
|
|
118
129
|
}
|
|
@@ -348,6 +359,12 @@ export function usdaLayerText(
|
|
|
348
359
|
...(layer.nomosReadGate !== undefined
|
|
349
360
|
? [` custom string nomos:readGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadGate)))}`]
|
|
350
361
|
: []),
|
|
362
|
+
...(layer.nomosReadVisibility !== undefined
|
|
363
|
+
? [` custom string nomos:readVisibilityHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadVisibility)))}`]
|
|
364
|
+
: []),
|
|
365
|
+
...(layer.nomosEncryption !== undefined
|
|
366
|
+
? [` custom string nomos:encryptionHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosEncryption)))}`]
|
|
367
|
+
: []),
|
|
351
368
|
``,
|
|
352
369
|
...body,
|
|
353
370
|
` }`,
|
|
@@ -502,6 +519,36 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
502
519
|
readGate = { v: 1, queries: queriesRec, directives: directivesRec };
|
|
503
520
|
}
|
|
504
521
|
}
|
|
522
|
+
// The read-visibility gate (slice 5.1): per-aggregate required-read caps merged
|
|
523
|
+
// later-wins, SORTED keys (matching the composed emission). Omit-when-empty.
|
|
524
|
+
let readVisibility: UsdLayer["nomosReadVisibility"];
|
|
525
|
+
{
|
|
526
|
+
const a = new Map<string, { requires: string }>();
|
|
527
|
+
for (const l of stack) {
|
|
528
|
+
if (l.nomosReadVisibility === undefined) continue;
|
|
529
|
+
for (const [type, spec] of Object.entries(l.nomosReadVisibility.aggregates)) a.set(type, spec);
|
|
530
|
+
}
|
|
531
|
+
if (a.size > 0) {
|
|
532
|
+
const aggregatesRec: Record<string, { requires: string }> = {};
|
|
533
|
+
for (const k of [...a.keys()].sort()) aggregatesRec[k] = a.get(k)!;
|
|
534
|
+
readVisibility = { v: 1, aggregates: aggregatesRec };
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// The encryption gate (slice 2): per-aggregate encrypted-field sets merged later-wins,
|
|
538
|
+
// SORTED keys (matching the composed emission). Omit-when-empty.
|
|
539
|
+
let encryption: UsdLayer["nomosEncryption"];
|
|
540
|
+
{
|
|
541
|
+
const a = new Map<string, { scope: string; fields: string[]; delegatable: false }>();
|
|
542
|
+
for (const l of stack) {
|
|
543
|
+
if (l.nomosEncryption === undefined) continue;
|
|
544
|
+
for (const [type, spec] of Object.entries(l.nomosEncryption.aggregates)) a.set(type, spec);
|
|
545
|
+
}
|
|
546
|
+
if (a.size > 0) {
|
|
547
|
+
const aggregatesRec: Record<string, { scope: string; fields: string[]; delegatable: false }> = {};
|
|
548
|
+
for (const k of [...a.keys()].sort()) aggregatesRec[k] = a.get(k)!;
|
|
549
|
+
encryption = { v: 1, aggregates: aggregatesRec };
|
|
550
|
+
}
|
|
551
|
+
}
|
|
505
552
|
return {
|
|
506
553
|
path,
|
|
507
554
|
prims: [...prims.keys()].sort().map((p) => prims.get(p)!),
|
|
@@ -510,6 +557,8 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
510
557
|
...(combineds !== undefined ? { combineds } : {}),
|
|
511
558
|
...(stableIds !== undefined ? { nomosStableIds: stableIds } : {}),
|
|
512
559
|
...(readGate !== undefined ? { nomosReadGate: readGate } : {}),
|
|
560
|
+
...(readVisibility !== undefined ? { nomosReadVisibility: readVisibility } : {}),
|
|
561
|
+
...(encryption !== undefined ? { nomosEncryption: encryption } : {}),
|
|
513
562
|
};
|
|
514
563
|
});
|
|
515
564
|
|
|
@@ -629,6 +678,8 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
629
678
|
const domainByScope = new Map<string, string>();
|
|
630
679
|
const stableIdsByDomain = new Map<string, UsdLayer["nomosStableIds"]>();
|
|
631
680
|
const readGateByDomain = new Map<string, UsdLayer["nomosReadGate"]>();
|
|
681
|
+
const readVisibilityByDomain = new Map<string, UsdLayer["nomosReadVisibility"]>();
|
|
682
|
+
const encryptionByDomain = new Map<string, UsdLayer["nomosEncryption"]>();
|
|
632
683
|
for (const p of prims) {
|
|
633
684
|
if (p.attrs.get("nomos:kind") === "domain") {
|
|
634
685
|
const domain = attrString(p, "nomos:domain");
|
|
@@ -642,6 +693,16 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
642
693
|
if (typeof rgHex === "string") {
|
|
643
694
|
readGateByDomain.set(domain, JSON.parse(unhexUtf8(rgHex)) as UsdLayer["nomosReadGate"]);
|
|
644
695
|
}
|
|
696
|
+
// THE READ-VISIBILITY GATE (slice 5.1): the hex-carried per-aggregate cap map.
|
|
697
|
+
const rvHex = p.attrs.get("nomos:readVisibilityHex");
|
|
698
|
+
if (typeof rvHex === "string") {
|
|
699
|
+
readVisibilityByDomain.set(domain, JSON.parse(unhexUtf8(rvHex)) as UsdLayer["nomosReadVisibility"]);
|
|
700
|
+
}
|
|
701
|
+
// THE ENCRYPTION GATE (slice 2): the hex-carried per-aggregate encrypted-field map.
|
|
702
|
+
const encHex = p.attrs.get("nomos:encryptionHex");
|
|
703
|
+
if (typeof encHex === "string") {
|
|
704
|
+
encryptionByDomain.set(domain, JSON.parse(unhexUtf8(encHex)) as UsdLayer["nomosEncryption"]);
|
|
705
|
+
}
|
|
645
706
|
}
|
|
646
707
|
}
|
|
647
708
|
|
|
@@ -731,6 +792,8 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
731
792
|
const b = buckets.get(domain)!;
|
|
732
793
|
const sids = stableIdsByDomain.get(domain);
|
|
733
794
|
const rg = readGateByDomain.get(domain);
|
|
795
|
+
const rv = readVisibilityByDomain.get(domain);
|
|
796
|
+
const enc = encryptionByDomain.get(domain);
|
|
734
797
|
return {
|
|
735
798
|
path: `/Nomos/${domain}`,
|
|
736
799
|
prims: [...b.prims].sort(byPath),
|
|
@@ -739,6 +802,8 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
739
802
|
...(b.combineds.length > 0 ? { combineds: [...b.combineds].sort(byId) } : {}),
|
|
740
803
|
...(sids !== undefined ? { nomosStableIds: sids } : {}),
|
|
741
804
|
...(rg !== undefined ? { nomosReadGate: rg } : {}),
|
|
805
|
+
...(rv !== undefined ? { nomosReadVisibility: rv } : {}),
|
|
806
|
+
...(enc !== undefined ? { nomosEncryption: enc } : {}),
|
|
742
807
|
};
|
|
743
808
|
})
|
|
744
809
|
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
package/src/wire.ts
CHANGED
|
@@ -130,19 +130,23 @@ export interface WireRead {
|
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* `Driver` — the kernel's externally-tagged serde encoding (`nomos2/kernel/src/lib.rs`).
|
|
133
|
-
* Unit variants → bare strings; `MapOf` → `{ MapOf: <inner> }
|
|
134
|
-
*
|
|
135
|
-
* drivers `RemoveWins` / `Counter` /
|
|
133
|
+
* Unit variants → bare strings; `MapOf` → `{ MapOf: <inner> }`; the newtype `LwwBy(String)`
|
|
134
|
+
* → `{ LwwBy: <principal> }`. This mirrors the kernel variants the DSL `encodeDriver` emits:
|
|
135
|
+
* the four originals, the structural CRDT unit drivers `RemoveWins` / `Counter` /
|
|
136
|
+
* `LastPosition`, and the EXPLICIT TIME-AUTHORITY drivers `LwwCausal` (causal-only LWW) /
|
|
137
|
+
* `LwwBy` (principal-as-time-authority LWW) — each a real `merge_field` arm.
|
|
136
138
|
* (`NumericMax`/`NumericMin`/`ImmutableAfterCreate`/`OrderedList` are kernel variants no
|
|
137
139
|
* DSL driver encodes to yet — added here only as the DSL gains a constant for them.)
|
|
138
140
|
*/
|
|
139
141
|
export type WireDriver =
|
|
140
142
|
| "Lww"
|
|
143
|
+
| "LwwCausal"
|
|
141
144
|
| "AddWins"
|
|
142
145
|
| "Conflict"
|
|
143
146
|
| "RemoveWins"
|
|
144
147
|
| "Counter"
|
|
145
148
|
| "LastPosition"
|
|
149
|
+
| { LwwBy: string }
|
|
146
150
|
| { MapOf: WireDriver };
|
|
147
151
|
|
|
148
152
|
/** `Schema = BTreeMap<FieldId, Driver>` — a plain object, field -> Driver. */
|