@githolon/dsl 0.14.0 → 0.16.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/dart/example/nomos_webview_transport.dart +2 -2
- package/dart/lib/nomos_dsl.dart +4 -4
- package/dart/lib/src/{dispatch.dart → offer.dart} +7 -7
- package/dart/lib/src/provider.dart +30 -30
- package/dart/lib/src/subscriptions.dart +3 -3
- package/dart/lib/src/webview_bridge.dart +56 -21
- package/dart/test/webview_bridge_test.dart +35 -34
- package/package.json +5 -3
- package/src/aggregate.ts +9 -1
- package/src/authoring.ts +10 -1
- package/src/build_package.ts +1 -1
- package/src/capability_exports.ts +2 -2
- package/src/codegen_dart.ts +34 -24
- package/src/codegen_dart_client.ts +74 -12
- package/src/codegen_provider_dart.ts +67 -61
- package/src/codegen_ts.ts +45 -17
- package/src/compile_package_main.ts +103 -36
- package/src/ctx.ts +13 -0
- package/src/engine_entry.ts +22 -5
- package/src/fields.ts +44 -0
- package/src/flow_gate.ts +208 -0
- package/src/framework/capability.ts +29 -11
- package/src/framework/encryption_scope.ts +9 -1
- package/src/framework/genesis.ts +5 -1
- package/src/framework/impure_capability.ts +73 -67
- package/src/framework/relations.ts +23 -4
- package/src/framework/signing_identity.ts +1 -1
- package/src/framework/sync_lifecycle.ts +3 -3
- package/src/framework/workspace_invariant.ts +29 -8
- package/src/framework/workspaces.ts +7 -0
- package/src/index.ts +25 -1
- package/src/manifest.ts +11 -17
- package/src/ops.ts +42 -1
- package/src/principal_evidence.ts +112 -0
- package/src/relation_sugar.ts +10 -4
- package/src/shape_compat.ts +208 -0
- package/src/usd.ts +287 -0
- package/src/usd_layers.ts +213 -26
- package/src/wire.ts +8 -0
- package/src/wire_encode.ts +75 -2
- package/src/workspace_sharding.ts +197 -24
- package/src/workspace_type.ts +1 -0
package/src/usd.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
type CanonicalManifest,
|
|
34
34
|
type CanonicalProjectionReturn,
|
|
35
35
|
} from "./manifest.js";
|
|
36
|
+
import type { AggregateHandle } from "./aggregate.js";
|
|
36
37
|
import {
|
|
37
38
|
mergeRequiresScope,
|
|
38
39
|
CompositionViolation,
|
|
@@ -40,7 +41,9 @@ import {
|
|
|
40
41
|
} from "./compose.js";
|
|
41
42
|
import type { WireSchema, WireRefMode } from "./wire.js";
|
|
42
43
|
import type { DomainModule } from "./codegen_dart.js";
|
|
44
|
+
import { domainInterface } from "./shape_compat.js";
|
|
43
45
|
import { relationType, user, key, anyUser } from "./relation_schema.js";
|
|
46
|
+
import { harvestPrincipalFlows } from "./wire_encode.js";
|
|
44
47
|
|
|
45
48
|
/** The referential marker of a directive prim (kernel `RefMode` wire string). */
|
|
46
49
|
export type RefMode = WireRefMode;
|
|
@@ -126,10 +129,46 @@ export interface UsdCombined {
|
|
|
126
129
|
readonly returns: CanonicalProjectionReturn;
|
|
127
130
|
}
|
|
128
131
|
|
|
132
|
+
/** One field's read-projection descriptor: the field kind plus a map's value kind. */
|
|
133
|
+
export interface UsdFieldKindDescriptor {
|
|
134
|
+
readonly kind: string;
|
|
135
|
+
readonly mapValueKind?: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface UsdReadProjection {
|
|
139
|
+
readonly aggregateFieldKinds: Record<string, Record<string, UsdFieldKindDescriptor>>;
|
|
140
|
+
readonly queries: { id: string; key: { field: string; kind: string }[]; returns: string }[];
|
|
141
|
+
readonly counts: { id: string; of: string; by: string | null; where?: unknown }[];
|
|
142
|
+
readonly spatials: { id: string; of: string; on: string }[];
|
|
143
|
+
readonly deriveds: { id: string; of: string; returns: CanonicalProjectionReturn }[];
|
|
144
|
+
readonly combineds: { id: string; of: string; refField: string; reads: string; returns: CanonicalProjectionReturn }[];
|
|
145
|
+
readonly sums?: { id: string; of: string; field: string; by: string | null; where?: unknown }[];
|
|
146
|
+
readonly mins?: { id: string; of: string; field: string; by: string | null; where?: unknown }[];
|
|
147
|
+
readonly maxes?: { id: string; of: string; field: string; by: string | null; where?: unknown }[];
|
|
148
|
+
readonly orderedReads?: {
|
|
149
|
+
id: string;
|
|
150
|
+
of: string;
|
|
151
|
+
orderKey: string;
|
|
152
|
+
orderDesc?: true;
|
|
153
|
+
where?: unknown;
|
|
154
|
+
limit: number;
|
|
155
|
+
}[];
|
|
156
|
+
}
|
|
157
|
+
|
|
129
158
|
/** One USD layer: a stage path + its prims (canonically sorted by prim path). */
|
|
130
159
|
export interface UsdLayer {
|
|
131
160
|
readonly path: string;
|
|
132
161
|
readonly prims: UsdPrim[];
|
|
162
|
+
/**
|
|
163
|
+
* The canonical admission/merge manifest for this layer, committed inside the package.
|
|
164
|
+
* Hosts must not stage or mutate this view; holons derive it from active installed law.
|
|
165
|
+
*/
|
|
166
|
+
readonly nomosIdentityManifest?: CanonicalManifest;
|
|
167
|
+
/**
|
|
168
|
+
* The projection schema/read-routing fragment for this layer, committed inside the package.
|
|
169
|
+
* It carries the projection-only field-kind data that cannot be recovered from merge drivers.
|
|
170
|
+
*/
|
|
171
|
+
readonly nomosReadProjection?: UsdReadProjection;
|
|
133
172
|
/**
|
|
134
173
|
* The layer's NAMED, INDEXED read declarations (read-side closure step 1), SORTED
|
|
135
174
|
* by id. OMITTED (`undefined`) when the module declares no query, so a query-free
|
|
@@ -255,6 +294,15 @@ export interface UsdLayer {
|
|
|
255
294
|
* whose old AND new packages both carry this key is DIFFED BY SID at the one gate.
|
|
256
295
|
*/
|
|
257
296
|
readonly nomosStableIds?: import("./stable_ids_types.js").StableIds;
|
|
297
|
+
/**
|
|
298
|
+
* THE STRUCTURAL INTERFACE (#72) — this domain's directives (payload shapes) + aggregates
|
|
299
|
+
* (read shapes, sid-keyed). ON-LEDGER (it rides the package, which installs as the
|
|
300
|
+
* `policy:{hash}.bundle`), so a client reads the workspace's OFFER straight from the folded
|
|
301
|
+
* law — reactively, host-blind (architecture/shape_compatibility.md). A client negotiates
|
|
302
|
+
* shape-compatibility against THIS, not the package hash. Pre-#72 bundles omit it; a client
|
|
303
|
+
* then reports `offerKnown:false` and never refuses on its absence (era-safe, graceful).
|
|
304
|
+
*/
|
|
305
|
+
readonly nomosInterface?: import("./shape_compat.js").DomainInterface;
|
|
258
306
|
/**
|
|
259
307
|
* THE CAPTURED-READ GATE DECLARATION (#58). Present IFF ≥1 directive of this layer
|
|
260
308
|
* declares a captured-read query (`.reads(someQuery)`): the law's EXPLICIT opt-in
|
|
@@ -304,6 +352,47 @@ export interface UsdLayer {
|
|
|
304
352
|
readonly v: 1;
|
|
305
353
|
readonly aggregates: Record<string, { scope: string; fields: string[]; delegatable: false }>;
|
|
306
354
|
};
|
|
355
|
+
/**
|
|
356
|
+
* THE CAPABILITY DECLARATION IN LAW (Full-A — capability_marketplace.md §4): the impure-
|
|
357
|
+
* capability quartets (obligation/complete/fail/block/deadLetter) lowered into the SEALED
|
|
358
|
+
* law, so the holon SURFACES them on the `declared_capabilities` read and the host relays a
|
|
359
|
+
* deploy-time "declared — bind it or obligations wait" notice without reaching into root
|
|
360
|
+
* law-state (boundness stays P6 — it is cross-holon root state). OMITTED for capability-free
|
|
361
|
+
* law (byte-identical hash — the era rule); declaring a capability MOVES the domainHash
|
|
362
|
+
* (named, expected). SORTED by aggregateId.
|
|
363
|
+
*/
|
|
364
|
+
readonly nomosCapabilities?: {
|
|
365
|
+
readonly v: 1;
|
|
366
|
+
readonly capabilities: readonly {
|
|
367
|
+
readonly capability: string;
|
|
368
|
+
readonly aggregateId: string;
|
|
369
|
+
readonly obligation: string;
|
|
370
|
+
readonly complete: string;
|
|
371
|
+
readonly fail: string;
|
|
372
|
+
readonly block: string;
|
|
373
|
+
readonly deadLetter: string;
|
|
374
|
+
readonly tasksQueryId: string | null;
|
|
375
|
+
/** The HTTPS endpoint the obligation is offered to (outbox); absent ⇒ no destination. */
|
|
376
|
+
readonly endpoint?: string;
|
|
377
|
+
}[];
|
|
378
|
+
};
|
|
379
|
+
/**
|
|
380
|
+
* THE FLOW GATE WAIVERS (architecture/security_model.md) — both halves of the audit surface,
|
|
381
|
+
* hashed into the law + replay-verified. `declassify` (confidentiality, rule 4): every acknowledged
|
|
382
|
+
* secret-correlated refusal. `endorse` (the integrity dual): every harvested PrincipalEvidence flow
|
|
383
|
+
* into an authority/standing/attribution sink — discovery IS law, witnessed fail-closed at runtime.
|
|
384
|
+
* Each half is OMITTED when empty (the era rule — a flow-free domain is byte-identical).
|
|
385
|
+
*/
|
|
386
|
+
readonly nomosFlowGate?: {
|
|
387
|
+
readonly v: 1;
|
|
388
|
+
readonly declassify?: readonly { readonly site: string; readonly reason: string }[];
|
|
389
|
+
readonly endorse?: readonly {
|
|
390
|
+
readonly directiveId: string;
|
|
391
|
+
readonly sink: string;
|
|
392
|
+
readonly facet: string;
|
|
393
|
+
readonly reason: string | null;
|
|
394
|
+
}[];
|
|
395
|
+
};
|
|
307
396
|
}
|
|
308
397
|
|
|
309
398
|
/** The reserved variant name declaring a set's DEFAULT (USD has a default variant). */
|
|
@@ -363,6 +452,123 @@ function encodeModuleToPrims(layerPath: string, mod: DomainModule): UsdPrim[] {
|
|
|
363
452
|
return sortPrims(prims);
|
|
364
453
|
}
|
|
365
454
|
|
|
455
|
+
function aggregateFieldKindsForModule(
|
|
456
|
+
mod: DomainModule,
|
|
457
|
+
): Record<string, Record<string, UsdFieldKindDescriptor>> {
|
|
458
|
+
const out: Record<string, Record<string, UsdFieldKindDescriptor>> = {};
|
|
459
|
+
for (const agg of [...(mod.aggregates as AggregateHandle[])].sort((a, b) =>
|
|
460
|
+
a.id < b.id ? -1 : a.id > b.id ? 1 : 0,
|
|
461
|
+
)) {
|
|
462
|
+
const fields: Record<string, UsdFieldKindDescriptor> = {};
|
|
463
|
+
for (const name of Object.keys(agg.fields).sort()) {
|
|
464
|
+
const field = agg.fields[name]!;
|
|
465
|
+
fields[name] = {
|
|
466
|
+
kind: field.kind,
|
|
467
|
+
...(field.mapValueKind !== undefined ? { mapValueKind: field.mapValueKind } : {}),
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
out[agg.id] = fields;
|
|
471
|
+
}
|
|
472
|
+
return out;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function readKeyFieldKind(
|
|
476
|
+
byType: Record<string, Record<string, UsdFieldKindDescriptor>>,
|
|
477
|
+
queryId: string,
|
|
478
|
+
returns: string,
|
|
479
|
+
keyField: string,
|
|
480
|
+
): string {
|
|
481
|
+
const schema = byType[returns];
|
|
482
|
+
if (schema === undefined) {
|
|
483
|
+
throw new Error(
|
|
484
|
+
`usd: query '${queryId}' returns '${returns}', which has no field schema in nomosReadProjection`,
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
const lookup = keyField.includes(".") ? keyField.split(".")[0]! : keyField;
|
|
488
|
+
const descriptor = schema[lookup];
|
|
489
|
+
if (descriptor === undefined) {
|
|
490
|
+
throw new Error(
|
|
491
|
+
`usd: query '${queryId}' is keyed on '${keyField}' (field '${lookup}'), which '${returns}' does not declare`,
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
return descriptor.kind;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function readProjectionForModule(mod: DomainModule, manifest: CanonicalManifest): UsdReadProjection {
|
|
498
|
+
const aggregateFieldKinds = aggregateFieldKindsForModule(mod);
|
|
499
|
+
return {
|
|
500
|
+
aggregateFieldKinds,
|
|
501
|
+
queries: (manifest.queries ?? []).map((q) => ({
|
|
502
|
+
id: q.id,
|
|
503
|
+
key: q.key.map((field) => ({
|
|
504
|
+
field,
|
|
505
|
+
kind: readKeyFieldKind(aggregateFieldKinds, q.id, q.returns, field),
|
|
506
|
+
})),
|
|
507
|
+
returns: q.returns,
|
|
508
|
+
})),
|
|
509
|
+
counts: (manifest.counts ?? []).map((c) => ({
|
|
510
|
+
id: c.id,
|
|
511
|
+
of: c.of,
|
|
512
|
+
by: c.by ?? null,
|
|
513
|
+
...(c.where !== undefined ? { where: c.where } : {}),
|
|
514
|
+
})),
|
|
515
|
+
spatials: (manifest.spatials ?? []).map((s) => ({ id: s.id, of: s.of, on: s.on })),
|
|
516
|
+
deriveds: (manifest.deriveds ?? []).map((d) => ({ id: d.id, of: d.of, returns: d.returns })),
|
|
517
|
+
combineds: (manifest.combineds ?? []).map((c) => ({
|
|
518
|
+
id: c.id,
|
|
519
|
+
of: c.of,
|
|
520
|
+
refField: c.refField,
|
|
521
|
+
reads: c.reads,
|
|
522
|
+
returns: c.returns,
|
|
523
|
+
})),
|
|
524
|
+
...((manifest.sums ?? []).length > 0
|
|
525
|
+
? {
|
|
526
|
+
sums: manifest.sums!.map((s) => ({
|
|
527
|
+
id: s.id,
|
|
528
|
+
of: s.of,
|
|
529
|
+
field: s.sumField,
|
|
530
|
+
by: s.by ?? null,
|
|
531
|
+
...(s.where !== undefined ? { where: s.where } : {}),
|
|
532
|
+
})),
|
|
533
|
+
}
|
|
534
|
+
: {}),
|
|
535
|
+
...((manifest.mins ?? []).length > 0
|
|
536
|
+
? {
|
|
537
|
+
mins: manifest.mins!.map((e) => ({
|
|
538
|
+
id: e.id,
|
|
539
|
+
of: e.of,
|
|
540
|
+
field: e.valueField,
|
|
541
|
+
by: e.by ?? null,
|
|
542
|
+
...(e.where !== undefined ? { where: e.where } : {}),
|
|
543
|
+
})),
|
|
544
|
+
}
|
|
545
|
+
: {}),
|
|
546
|
+
...((manifest.maxes ?? []).length > 0
|
|
547
|
+
? {
|
|
548
|
+
maxes: manifest.maxes!.map((e) => ({
|
|
549
|
+
id: e.id,
|
|
550
|
+
of: e.of,
|
|
551
|
+
field: e.valueField,
|
|
552
|
+
by: e.by ?? null,
|
|
553
|
+
...(e.where !== undefined ? { where: e.where } : {}),
|
|
554
|
+
})),
|
|
555
|
+
}
|
|
556
|
+
: {}),
|
|
557
|
+
...((manifest.orderedReads ?? []).length > 0
|
|
558
|
+
? {
|
|
559
|
+
orderedReads: manifest.orderedReads!.map((r) => ({
|
|
560
|
+
id: r.id,
|
|
561
|
+
of: r.of,
|
|
562
|
+
orderKey: r.orderKey,
|
|
563
|
+
...(r.orderDesc ? { orderDesc: true as const } : {}),
|
|
564
|
+
...(r.where !== undefined ? { where: r.where } : {}),
|
|
565
|
+
limit: r.limit,
|
|
566
|
+
})),
|
|
567
|
+
}
|
|
568
|
+
: {}),
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
366
572
|
/**
|
|
367
573
|
* Lower a layer's `relationType` decls into the canonical `nomosRelations` wire object (P1) —
|
|
368
574
|
* keys SORTED for byte-determinism, omit-when-empty (the era rule). Multiple decls for one type
|
|
@@ -546,14 +752,83 @@ export function emitUsd(
|
|
|
546
752
|
encAggregates[a.id] = { scope: a.requiresRead, fields: [...a.encryptedFields], delegatable: false };
|
|
547
753
|
}
|
|
548
754
|
}
|
|
755
|
+
// THE CAPABILITY DECLARATION IN LAW (Full-A — capability_marketplace.md §4): the
|
|
756
|
+
// impure-capability quartets lowered into the SEALED law, so the holon can SURFACE
|
|
757
|
+
// them on a read (`declared_capabilities`) and the host RELAYS a deploy-time notice
|
|
758
|
+
// ("declares 'x' — bind it or obligations wait") WITHOUT reaching into root law-state.
|
|
759
|
+
// Mirrors the deploy-sidecar `capabilityLowerings` extraction; SORTED by aggregate id;
|
|
760
|
+
// omit-when-empty so capability-free law is byte-identical (the era rule). Declaring a
|
|
761
|
+
// capability now MOVES the domainHash (named, expected — like the stable-ids key).
|
|
762
|
+
const nomosCapabilities = [...((l.module as { impureCapabilities?: readonly unknown[] }).impureCapabilities ?? [])]
|
|
763
|
+
.map((c) => {
|
|
764
|
+
const k = c as {
|
|
765
|
+
aggregate: { id: string };
|
|
766
|
+
obligation: { id: string };
|
|
767
|
+
complete: { id: string };
|
|
768
|
+
fail: { id: string };
|
|
769
|
+
block: { id: string };
|
|
770
|
+
deadLetter: { id: string };
|
|
771
|
+
name?: unknown;
|
|
772
|
+
capability?: unknown;
|
|
773
|
+
endpoint?: unknown;
|
|
774
|
+
tasks?: { id?: unknown };
|
|
775
|
+
};
|
|
776
|
+
const cap = typeof k.name === "string" ? k.name : typeof k.capability === "string" ? k.capability : null;
|
|
777
|
+
if (cap === null) return null; // a binding-free quartet declares nothing (omit-when-absent)
|
|
778
|
+
return {
|
|
779
|
+
capability: cap,
|
|
780
|
+
aggregateId: k.aggregate.id,
|
|
781
|
+
obligation: k.obligation.id,
|
|
782
|
+
complete: k.complete.id,
|
|
783
|
+
fail: k.fail.id,
|
|
784
|
+
block: k.block.id,
|
|
785
|
+
deadLetter: k.deadLetter.id,
|
|
786
|
+
tasksQueryId: typeof k.tasks?.id === "string" ? k.tasks.id : null,
|
|
787
|
+
...(typeof k.endpoint === "string" ? { endpoint: k.endpoint } : {}),
|
|
788
|
+
};
|
|
789
|
+
})
|
|
790
|
+
.filter((c): c is NonNullable<typeof c> => c !== null)
|
|
791
|
+
.sort((a, b) => (a.aggregateId < b.aggregateId ? -1 : a.aggregateId > b.aggregateId ? 1 : 0));
|
|
792
|
+
// THE DECLASSIFY SITES (nomosFlowGate rule 4 — security_model.md): every acknowledged
|
|
793
|
+
// intended secret-correlated refusal, with its human reason. Hashed into the law (it IS
|
|
794
|
+
// a law-declared waiver) + replay-verified — "the set of declassify sites is the entire
|
|
795
|
+
// audit surface". Omit-when-empty: a domain with no declassify is byte-identical.
|
|
796
|
+
const flowDeclassify = [
|
|
797
|
+
...[...(l.module.workspaceInvariants ?? [])]
|
|
798
|
+
.filter((wi) => typeof (wi as { declassify?: unknown }).declassify === "string")
|
|
799
|
+
.map((wi) => ({ site: `workspaceInvariant:${wi.id}`, reason: (wi as { declassify: string }).declassify })),
|
|
800
|
+
...[...(l.module.aggregates as { id: string; invariantDeclassify?: unknown }[])]
|
|
801
|
+
.filter((a) => typeof a.invariantDeclassify === "string")
|
|
802
|
+
.map((a) => ({ site: `aggregateInvariant:${a.id}`, reason: a.invariantDeclassify as string })),
|
|
803
|
+
...[...((l.module as { impureCapabilities?: readonly { name?: string; capability?: string; aggregate: { id: string }; declassify?: unknown }[] }).impureCapabilities ?? [])]
|
|
804
|
+
.filter((c) => typeof c.declassify === "string")
|
|
805
|
+
.map((c) => ({ site: `capability:${c.name ?? c.capability ?? c.aggregate.id}`, reason: c.declassify as string })),
|
|
806
|
+
].sort((a, b) => (a.site < b.site ? -1 : a.site > b.site ? 1 : 0));
|
|
807
|
+
// THE ENDORSE FLOWS (the integrity dual — security_model.md): discovery IS law. Run each
|
|
808
|
+
// directive's pure plan with a probe principal + payload and harvest every PrincipalEvidence
|
|
809
|
+
// conversion's declared flow {directiveId, sink, facet, reason}. Hashed into nomosFlowGate +
|
|
810
|
+
// witnessed fail-closed at runtime (Slice B). Omit-when-empty (a principal-free domain is
|
|
811
|
+
// byte-identical). SORTED for determinism.
|
|
812
|
+
const flowEndorse = [...l.module.directives]
|
|
813
|
+
.flatMap((d) => harvestPrincipalFlows(d as never).map((f) => ({ directiveId: d.id, sink: f.sink, facet: f.facet, reason: f.reason })))
|
|
814
|
+
.sort((a, b) =>
|
|
815
|
+
a.directiveId !== b.directiveId ? (a.directiveId < b.directiveId ? -1 : 1)
|
|
816
|
+
: a.sink !== b.sink ? (a.sink < b.sink ? -1 : 1)
|
|
817
|
+
: a.facet < b.facet ? -1 : a.facet > b.facet ? 1 : 0,
|
|
818
|
+
);
|
|
549
819
|
return {
|
|
550
820
|
path: l.path,
|
|
551
821
|
prims: encodeModuleToPrims(l.path, l.module),
|
|
822
|
+
nomosIdentityManifest: manifest,
|
|
823
|
+
nomosReadProjection: readProjectionForModule(l.module, manifest),
|
|
552
824
|
...(manifest.queries !== undefined ? { queries: manifest.queries } : {}),
|
|
553
825
|
...(manifest.deriveds !== undefined ? { deriveds: manifest.deriveds } : {}),
|
|
554
826
|
...(manifest.combineds !== undefined ? { combineds: manifest.combineds } : {}),
|
|
555
827
|
// STABLE IDS (#58): every post-#58 compile carries them (the era key).
|
|
556
828
|
...(manifest.stableIds !== undefined ? { nomosStableIds: manifest.stableIds } : {}),
|
|
829
|
+
// THE STRUCTURAL INTERFACE (#72): the on-ledger OFFER — a client negotiates shape-
|
|
830
|
+
// compatibility against this, reactively, straight from the folded `policy:{hash}.bundle`.
|
|
831
|
+
nomosInterface: domainInterface(l.module, manifest.stableIds),
|
|
557
832
|
...(Object.keys(readGateDirectives).length > 0
|
|
558
833
|
? {
|
|
559
834
|
nomosReadGate: {
|
|
@@ -581,6 +856,18 @@ export function emitUsd(
|
|
|
581
856
|
...(Object.keys(encAggregates).length > 0
|
|
582
857
|
? { nomosEncryption: { v: 1 as const, aggregates: encAggregates } }
|
|
583
858
|
: {}),
|
|
859
|
+
...(nomosCapabilities.length > 0
|
|
860
|
+
? { nomosCapabilities: { v: 1 as const, capabilities: nomosCapabilities } }
|
|
861
|
+
: {}),
|
|
862
|
+
...(flowDeclassify.length > 0 || flowEndorse.length > 0
|
|
863
|
+
? {
|
|
864
|
+
nomosFlowGate: {
|
|
865
|
+
v: 1 as const,
|
|
866
|
+
...(flowDeclassify.length > 0 ? { declassify: flowDeclassify } : {}),
|
|
867
|
+
...(flowEndorse.length > 0 ? { endorse: flowEndorse } : {}),
|
|
868
|
+
},
|
|
869
|
+
}
|
|
870
|
+
: {}),
|
|
584
871
|
};
|
|
585
872
|
})
|
|
586
873
|
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
package/src/usd_layers.ts
CHANGED
|
@@ -143,6 +143,43 @@ function sortedSchema(schema: WireSchema): WireSchema {
|
|
|
143
143
|
return out;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
function domainLayerAttrLines(domain: string, layer: UsdLayer, indent: string): string[] {
|
|
147
|
+
return [
|
|
148
|
+
`${indent}custom string nomos:kind = "domain"`,
|
|
149
|
+
`${indent}custom string nomos:domain = ${usdaString(domain)}`,
|
|
150
|
+
...(layer.nomosIdentityManifest !== undefined
|
|
151
|
+
? [`${indent}custom string nomos:identityManifestHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosIdentityManifest)))}`]
|
|
152
|
+
: []),
|
|
153
|
+
...(layer.nomosReadProjection !== undefined
|
|
154
|
+
? [`${indent}custom string nomos:readProjectionHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadProjection)))}`]
|
|
155
|
+
: []),
|
|
156
|
+
...(layer.nomosStableIds !== undefined
|
|
157
|
+
? [`${indent}custom string nomos:stableIdsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosStableIds)))}`]
|
|
158
|
+
: []),
|
|
159
|
+
...(layer.nomosInterface !== undefined
|
|
160
|
+
? [`${indent}custom string nomos:interfaceHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosInterface)))}`]
|
|
161
|
+
: []),
|
|
162
|
+
...(layer.nomosReadGate !== undefined
|
|
163
|
+
? [`${indent}custom string nomos:readGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadGate)))}`]
|
|
164
|
+
: []),
|
|
165
|
+
...(layer.nomosReadVisibility !== undefined
|
|
166
|
+
? [`${indent}custom string nomos:readVisibilityHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadVisibility)))}`]
|
|
167
|
+
: []),
|
|
168
|
+
...(layer.nomosEncryption !== undefined
|
|
169
|
+
? [`${indent}custom string nomos:encryptionHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosEncryption)))}`]
|
|
170
|
+
: []),
|
|
171
|
+
...(layer.nomosRelations !== undefined
|
|
172
|
+
? [`${indent}custom string nomos:relationsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelations)))}`]
|
|
173
|
+
: []),
|
|
174
|
+
...(layer.nomosRelationGate !== undefined
|
|
175
|
+
? [`${indent}custom string nomos:relationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelationGate)))}`]
|
|
176
|
+
: []),
|
|
177
|
+
...(layer.nomosAttestationGate !== undefined
|
|
178
|
+
? [`${indent}custom string nomos:attestationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosAttestationGate)))}`]
|
|
179
|
+
: []),
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
|
|
146
183
|
// ── per-module layer emission ────────────────────────────────────────────────────────
|
|
147
184
|
|
|
148
185
|
/** One authored module of a domain's ordered module list (weak → strong). */
|
|
@@ -349,31 +386,9 @@ export function usdaLayerText(
|
|
|
349
386
|
`{`,
|
|
350
387
|
` def Scope ${usdaString(primName(domain))}`,
|
|
351
388
|
` {`,
|
|
352
|
-
|
|
353
|
-
` custom string nomos:domain = ${usdaString(domain)}`,
|
|
354
|
-
// STABLE IDS + the captured-read gate (#58): layer-level law keys, hex-carried
|
|
389
|
+
// Stable ids + holon-owned manifests: layer-level law keys, hex-carried
|
|
355
390
|
// so the .usda round-trips byte-faithfully to the IR layer.
|
|
356
|
-
...(layer
|
|
357
|
-
? [` custom string nomos:stableIdsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosStableIds)))}`]
|
|
358
|
-
: []),
|
|
359
|
-
...(layer.nomosReadGate !== undefined
|
|
360
|
-
? [` custom string nomos:readGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadGate)))}`]
|
|
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
|
-
: []),
|
|
368
|
-
...(layer.nomosRelations !== undefined
|
|
369
|
-
? [` custom string nomos:relationsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelations)))}`]
|
|
370
|
-
: []),
|
|
371
|
-
...(layer.nomosRelationGate !== undefined
|
|
372
|
-
? [` custom string nomos:relationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelationGate)))}`]
|
|
373
|
-
: []),
|
|
374
|
-
...(layer.nomosAttestationGate !== undefined
|
|
375
|
-
? [` custom string nomos:attestationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosAttestationGate)))}`]
|
|
376
|
-
: []),
|
|
391
|
+
...domainLayerAttrLines(domain, layer, " "),
|
|
377
392
|
``,
|
|
378
393
|
...body,
|
|
379
394
|
` }`,
|
|
@@ -388,8 +403,30 @@ export function usdaLayerText(
|
|
|
388
403
|
* list is STRONGEST-FIRST, so the list is emitted REVERSED. Same monoid, opposite
|
|
389
404
|
* notation — the reversal IS the correspondence, recorded in the doc string.
|
|
390
405
|
*/
|
|
391
|
-
export function layeredRootUsda(
|
|
406
|
+
export function layeredRootUsda(
|
|
407
|
+
sublayerRelPathsWeakToStrong: readonly string[],
|
|
408
|
+
composed?: UsdDocument,
|
|
409
|
+
): string {
|
|
392
410
|
const strongestFirst = [...sublayerRelPathsWeakToStrong].reverse();
|
|
411
|
+
const composedDomainOpinions =
|
|
412
|
+
composed === undefined || composed.layers.length === 0
|
|
413
|
+
? []
|
|
414
|
+
: [
|
|
415
|
+
``,
|
|
416
|
+
`over "Nomos"`,
|
|
417
|
+
`{`,
|
|
418
|
+
...composed.layers.flatMap((layer) => {
|
|
419
|
+
const domain = layer.path.slice(layer.path.lastIndexOf("/") + 1);
|
|
420
|
+
return [
|
|
421
|
+
` over ${usdaString(primName(domain))}`,
|
|
422
|
+
` {`,
|
|
423
|
+
...domainLayerAttrLines(domain, layer, " "),
|
|
424
|
+
` }`,
|
|
425
|
+
];
|
|
426
|
+
}),
|
|
427
|
+
`}`,
|
|
428
|
+
``,
|
|
429
|
+
];
|
|
393
430
|
return [
|
|
394
431
|
`#usda 1.0`,
|
|
395
432
|
`(`,
|
|
@@ -406,6 +443,7 @@ export function layeredRootUsda(sublayerRelPathsWeakToStrong: readonly string[])
|
|
|
406
443
|
),
|
|
407
444
|
` ]`,
|
|
408
445
|
`)`,
|
|
446
|
+
...composedDomainOpinions,
|
|
409
447
|
``,
|
|
410
448
|
].join("\n");
|
|
411
449
|
}
|
|
@@ -461,6 +499,97 @@ function foldById<T extends { readonly id: string }>(
|
|
|
461
499
|
return [...byId.keys()].sort().map((id) => byId.get(id)!);
|
|
462
500
|
}
|
|
463
501
|
|
|
502
|
+
function foldByKey<T>(
|
|
503
|
+
lists: readonly (readonly T[] | undefined)[],
|
|
504
|
+
keyOf: (item: T) => string,
|
|
505
|
+
): T[] | undefined {
|
|
506
|
+
const byKey = new Map<string, T>();
|
|
507
|
+
for (const list of lists) for (const item of list ?? []) byKey.set(keyOf(item), item);
|
|
508
|
+
if (byKey.size === 0) return undefined;
|
|
509
|
+
return [...byKey.keys()].sort().map((key) => byKey.get(key)!);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function foldRecord<T>(
|
|
513
|
+
records: readonly (Readonly<Record<string, T>> | undefined)[],
|
|
514
|
+
): Record<string, T> | undefined {
|
|
515
|
+
const byKey = new Map<string, T>();
|
|
516
|
+
for (const record of records) {
|
|
517
|
+
if (record === undefined) continue;
|
|
518
|
+
for (const [key, value] of Object.entries(record)) byKey.set(key, value);
|
|
519
|
+
}
|
|
520
|
+
if (byKey.size === 0) return undefined;
|
|
521
|
+
const out: Record<string, T> = {};
|
|
522
|
+
for (const key of [...byKey.keys()].sort()) out[key] = byKey.get(key)!;
|
|
523
|
+
return out;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function foldIdentityManifest(
|
|
527
|
+
stack: readonly UsdLayer[],
|
|
528
|
+
stableIds: UsdLayer["nomosStableIds"],
|
|
529
|
+
): UsdLayer["nomosIdentityManifest"] {
|
|
530
|
+
const manifests = stack
|
|
531
|
+
.map((l) => l.nomosIdentityManifest)
|
|
532
|
+
.filter((m): m is NonNullable<UsdLayer["nomosIdentityManifest"]> => m !== undefined);
|
|
533
|
+
if (manifests.length === 0) return undefined;
|
|
534
|
+
const domain = manifests[manifests.length - 1]!.domain;
|
|
535
|
+
const workspaceInvariants = foldById(manifests.map((m) => m.workspaceInvariants));
|
|
536
|
+
const queries = foldById(manifests.map((m) => m.queries));
|
|
537
|
+
const counts = foldById(manifests.map((m) => m.counts));
|
|
538
|
+
const spatials = foldById(manifests.map((m) => m.spatials));
|
|
539
|
+
const sums = foldById(manifests.map((m) => m.sums));
|
|
540
|
+
const deriveds = foldById(manifests.map((m) => m.deriveds));
|
|
541
|
+
const combineds = foldById(manifests.map((m) => m.combineds));
|
|
542
|
+
const mins = foldById(manifests.map((m) => m.mins));
|
|
543
|
+
const maxes = foldById(manifests.map((m) => m.maxes));
|
|
544
|
+
const orderedReads = foldById(manifests.map((m) => m.orderedReads));
|
|
545
|
+
const workspaceTypes = foldById(manifests.map((m) => m.workspaceTypes));
|
|
546
|
+
const homes = foldRecord(manifests.map((m) => m.homes));
|
|
547
|
+
const routes = foldByKey(manifests.map((m) => m.routes), (r) => r.directive);
|
|
548
|
+
return {
|
|
549
|
+
domain,
|
|
550
|
+
aggregates: foldById(manifests.map((m) => m.aggregates)) ?? [],
|
|
551
|
+
directives: foldById(manifests.map((m) => m.directives)) ?? [],
|
|
552
|
+
...(stableIds !== undefined ? { stableIds } : {}),
|
|
553
|
+
...(workspaceInvariants !== undefined ? { workspaceInvariants } : {}),
|
|
554
|
+
...(queries !== undefined ? { queries } : {}),
|
|
555
|
+
...(counts !== undefined ? { counts } : {}),
|
|
556
|
+
...(spatials !== undefined ? { spatials } : {}),
|
|
557
|
+
...(sums !== undefined ? { sums } : {}),
|
|
558
|
+
...(deriveds !== undefined ? { deriveds } : {}),
|
|
559
|
+
...(combineds !== undefined ? { combineds } : {}),
|
|
560
|
+
...(mins !== undefined ? { mins } : {}),
|
|
561
|
+
...(maxes !== undefined ? { maxes } : {}),
|
|
562
|
+
...(orderedReads !== undefined ? { orderedReads } : {}),
|
|
563
|
+
...(workspaceTypes !== undefined ? { workspaceTypes } : {}),
|
|
564
|
+
...(homes !== undefined ? { homes } : {}),
|
|
565
|
+
...(routes !== undefined ? { routes } : {}),
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function foldReadProjection(stack: readonly UsdLayer[]): UsdLayer["nomosReadProjection"] {
|
|
570
|
+
const projections = stack
|
|
571
|
+
.map((l) => l.nomosReadProjection)
|
|
572
|
+
.filter((p): p is NonNullable<UsdLayer["nomosReadProjection"]> => p !== undefined);
|
|
573
|
+
if (projections.length === 0) return undefined;
|
|
574
|
+
const aggregateFieldKinds = foldRecord(projections.map((p) => p.aggregateFieldKinds)) ?? {};
|
|
575
|
+
const sums = foldById(projections.map((p) => p.sums));
|
|
576
|
+
const mins = foldById(projections.map((p) => p.mins));
|
|
577
|
+
const maxes = foldById(projections.map((p) => p.maxes));
|
|
578
|
+
const orderedReads = foldById(projections.map((p) => p.orderedReads));
|
|
579
|
+
return {
|
|
580
|
+
aggregateFieldKinds,
|
|
581
|
+
queries: foldById(projections.map((p) => p.queries)) ?? [],
|
|
582
|
+
counts: foldById(projections.map((p) => p.counts)) ?? [],
|
|
583
|
+
spatials: foldById(projections.map((p) => p.spatials)) ?? [],
|
|
584
|
+
deriveds: foldById(projections.map((p) => p.deriveds)) ?? [],
|
|
585
|
+
combineds: foldById(projections.map((p) => p.combineds)) ?? [],
|
|
586
|
+
...(sums !== undefined ? { sums } : {}),
|
|
587
|
+
...(mins !== undefined ? { mins } : {}),
|
|
588
|
+
...(maxes !== undefined ? { maxes } : {}),
|
|
589
|
+
...(orderedReads !== undefined ? { orderedReads } : {}),
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
464
593
|
/**
|
|
465
594
|
* THE ORDERED OPINION-MAP FOLD: flatten module layers (weak → strong within each
|
|
466
595
|
* stage path) into the effective single-layer-per-domain document. Strongest
|
|
@@ -509,6 +638,39 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
509
638
|
stableIds = { v: 1, domain: domainSid, aggregates };
|
|
510
639
|
}
|
|
511
640
|
}
|
|
641
|
+
// THE STRUCTURAL INTERFACE (#72): fold per-module interfaces — directives + aggregates merged
|
|
642
|
+
// later-wins, SORTED keys (matching the composed emission's sorted-key `domainInterface`).
|
|
643
|
+
let iface: UsdLayer["nomosInterface"];
|
|
644
|
+
{
|
|
645
|
+
type Dir = NonNullable<UsdLayer["nomosInterface"]>["directives"][string];
|
|
646
|
+
type Agg = NonNullable<UsdLayer["nomosInterface"]>["aggregates"][string];
|
|
647
|
+
const dirs = new Map<string, Dir>();
|
|
648
|
+
const aggsI = new Map<string, Agg>();
|
|
649
|
+
let domainI: string | undefined;
|
|
650
|
+
let domainSidI: string | undefined;
|
|
651
|
+
for (const l of stack) {
|
|
652
|
+
if (l.nomosInterface === undefined) continue;
|
|
653
|
+
domainI = l.nomosInterface.domain;
|
|
654
|
+
domainSidI = l.nomosInterface.domainSid;
|
|
655
|
+
for (const [id, spec] of Object.entries(l.nomosInterface.directives)) dirs.set(id, spec);
|
|
656
|
+
for (const [sid, spec] of Object.entries(l.nomosInterface.aggregates)) aggsI.set(sid, spec);
|
|
657
|
+
}
|
|
658
|
+
if (domainI !== undefined) {
|
|
659
|
+
const directivesRec: Record<string, Dir> = {};
|
|
660
|
+
for (const k of [...dirs.keys()].sort()) directivesRec[k] = dirs.get(k)!;
|
|
661
|
+
const aggregatesRec: Record<string, Agg> = {};
|
|
662
|
+
for (const k of [...aggsI.keys()].sort()) aggregatesRec[k] = aggsI.get(k)!;
|
|
663
|
+
iface = {
|
|
664
|
+
v: 1,
|
|
665
|
+
domain: domainI,
|
|
666
|
+
...(domainSidI !== undefined ? { domainSid: domainSidI } : {}),
|
|
667
|
+
directives: directivesRec,
|
|
668
|
+
aggregates: aggregatesRec,
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
const identityManifest = foldIdentityManifest(stack, stableIds);
|
|
673
|
+
const readProjection = foldReadProjection(stack);
|
|
512
674
|
// The captured-read gate (#58): queries + per-directive read sets merged
|
|
513
675
|
// later-wins, SORTED keys (matching the composed emission).
|
|
514
676
|
let readGate: UsdLayer["nomosReadGate"];
|
|
@@ -606,10 +768,13 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
606
768
|
return {
|
|
607
769
|
path,
|
|
608
770
|
prims: [...prims.keys()].sort().map((p) => prims.get(p)!),
|
|
771
|
+
...(identityManifest !== undefined ? { nomosIdentityManifest: identityManifest } : {}),
|
|
772
|
+
...(readProjection !== undefined ? { nomosReadProjection: readProjection } : {}),
|
|
609
773
|
...(queries !== undefined ? { queries } : {}),
|
|
610
774
|
...(deriveds !== undefined ? { deriveds } : {}),
|
|
611
775
|
...(combineds !== undefined ? { combineds } : {}),
|
|
612
776
|
...(stableIds !== undefined ? { nomosStableIds: stableIds } : {}),
|
|
777
|
+
...(iface !== undefined ? { nomosInterface: iface } : {}),
|
|
613
778
|
...(readGate !== undefined ? { nomosReadGate: readGate } : {}),
|
|
614
779
|
...(readVisibility !== undefined ? { nomosReadVisibility: readVisibility } : {}),
|
|
615
780
|
...(encryption !== undefined ? { nomosEncryption: encryption } : {}),
|
|
@@ -733,7 +898,10 @@ function attrStringArray(prim: ParsedPrim, name: string): string[] {
|
|
|
733
898
|
export function parseUsdaDocument(text: string): UsdDocument {
|
|
734
899
|
const prims = parseUsdaPrims(text);
|
|
735
900
|
const domainByScope = new Map<string, string>();
|
|
901
|
+
const identityManifestByDomain = new Map<string, UsdLayer["nomosIdentityManifest"]>();
|
|
902
|
+
const readProjectionByDomain = new Map<string, UsdLayer["nomosReadProjection"]>();
|
|
736
903
|
const stableIdsByDomain = new Map<string, UsdLayer["nomosStableIds"]>();
|
|
904
|
+
const interfaceByDomain = new Map<string, UsdLayer["nomosInterface"]>();
|
|
737
905
|
const readGateByDomain = new Map<string, UsdLayer["nomosReadGate"]>();
|
|
738
906
|
const readVisibilityByDomain = new Map<string, UsdLayer["nomosReadVisibility"]>();
|
|
739
907
|
const encryptionByDomain = new Map<string, UsdLayer["nomosEncryption"]>();
|
|
@@ -744,11 +912,24 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
744
912
|
if (p.attrs.get("nomos:kind") === "domain") {
|
|
745
913
|
const domain = attrString(p, "nomos:domain");
|
|
746
914
|
domainByScope.set(p.path, domain);
|
|
747
|
-
//
|
|
915
|
+
// Holon-owned manifests + gates: the hex-carried layer-level law keys.
|
|
916
|
+
const idHex = p.attrs.get("nomos:identityManifestHex");
|
|
917
|
+
if (typeof idHex === "string") {
|
|
918
|
+
identityManifestByDomain.set(domain, JSON.parse(unhexUtf8(idHex)) as UsdLayer["nomosIdentityManifest"]);
|
|
919
|
+
}
|
|
920
|
+
const rpHex = p.attrs.get("nomos:readProjectionHex");
|
|
921
|
+
if (typeof rpHex === "string") {
|
|
922
|
+
readProjectionByDomain.set(domain, JSON.parse(unhexUtf8(rpHex)) as UsdLayer["nomosReadProjection"]);
|
|
923
|
+
}
|
|
748
924
|
const sidHex = p.attrs.get("nomos:stableIdsHex");
|
|
749
925
|
if (typeof sidHex === "string") {
|
|
750
926
|
stableIdsByDomain.set(domain, JSON.parse(unhexUtf8(sidHex)) as UsdLayer["nomosStableIds"]);
|
|
751
927
|
}
|
|
928
|
+
// THE STRUCTURAL INTERFACE (#72): the on-ledger OFFER, hex-carried per domain layer.
|
|
929
|
+
const ifaceHex = p.attrs.get("nomos:interfaceHex");
|
|
930
|
+
if (typeof ifaceHex === "string") {
|
|
931
|
+
interfaceByDomain.set(domain, JSON.parse(unhexUtf8(ifaceHex)) as UsdLayer["nomosInterface"]);
|
|
932
|
+
}
|
|
752
933
|
const rgHex = p.attrs.get("nomos:readGateHex");
|
|
753
934
|
if (typeof rgHex === "string") {
|
|
754
935
|
readGateByDomain.set(domain, JSON.parse(unhexUtf8(rgHex)) as UsdLayer["nomosReadGate"]);
|
|
@@ -865,7 +1046,10 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
865
1046
|
const layers: UsdLayer[] = [...buckets.keys()]
|
|
866
1047
|
.map((domain) => {
|
|
867
1048
|
const b = buckets.get(domain)!;
|
|
1049
|
+
const identity = identityManifestByDomain.get(domain);
|
|
1050
|
+
const readProjection = readProjectionByDomain.get(domain);
|
|
868
1051
|
const sids = stableIdsByDomain.get(domain);
|
|
1052
|
+
const iface = interfaceByDomain.get(domain);
|
|
869
1053
|
const rg = readGateByDomain.get(domain);
|
|
870
1054
|
const rv = readVisibilityByDomain.get(domain);
|
|
871
1055
|
const enc = encryptionByDomain.get(domain);
|
|
@@ -875,10 +1059,13 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
875
1059
|
return {
|
|
876
1060
|
path: `/Nomos/${domain}`,
|
|
877
1061
|
prims: [...b.prims].sort(byPath),
|
|
1062
|
+
...(identity !== undefined ? { nomosIdentityManifest: identity } : {}),
|
|
1063
|
+
...(readProjection !== undefined ? { nomosReadProjection: readProjection } : {}),
|
|
878
1064
|
...(b.queries.length > 0 ? { queries: [...b.queries].sort(byId) } : {}),
|
|
879
1065
|
...(b.deriveds.length > 0 ? { deriveds: [...b.deriveds].sort(byId) } : {}),
|
|
880
1066
|
...(b.combineds.length > 0 ? { combineds: [...b.combineds].sort(byId) } : {}),
|
|
881
1067
|
...(sids !== undefined ? { nomosStableIds: sids } : {}),
|
|
1068
|
+
...(iface !== undefined ? { nomosInterface: iface } : {}),
|
|
882
1069
|
...(rg !== undefined ? { nomosReadGate: rg } : {}),
|
|
883
1070
|
...(rv !== undefined ? { nomosReadVisibility: rv } : {}),
|
|
884
1071
|
...(enc !== undefined ? { nomosEncryption: enc } : {}),
|