@githolon/dsl 0.102.5 → 0.103.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.
Files changed (131) hide show
  1. package/compile_package.mjs +43 -2
  2. package/compile_proof.d.mts +47 -0
  3. package/compile_proof.mjs +343 -0
  4. package/dart/CHANGELOG.md +7 -0
  5. package/dart/lib/src/dev_cloud.dart +8 -8
  6. package/dart/lib/src/nms_generated_runtime.dart +2 -0
  7. package/dart/lib/src/runner/node-entry.mjs +5504 -1236
  8. package/dart/lib/src/runner/offline-install.mjs +4578 -528
  9. package/dart/lib/src/test_harness.dart +206 -152
  10. package/dart/lib/src/webview_bridge.dart +196 -89
  11. package/dart/pubspec.lock +1 -1
  12. package/dart/pubspec.yaml +2 -2
  13. package/dart/test/acquire_session_credentials_test.dart +4 -3
  14. package/dart/test/adv_realm_interference_test.dart +7 -6
  15. package/dart/test/cloud_bound_topology_test.dart +3 -3
  16. package/dart/test/cluster_births_test.dart +4 -3
  17. package/dart/test/cluster_device_keyed_acceptance_test.dart +10 -16
  18. package/dart/test/cluster_local_autosync_test.dart +3 -2
  19. package/dart/test/cluster_scale_test.dart +3 -2
  20. package/dart/test/dlq_session_surface_test.dart +7 -6
  21. package/dart/test/first_app_gauntlet_test.dart +14 -21
  22. package/dart/test/fixtures/wedge/fake-install.mjs +1 -1
  23. package/dart/test/four_layer_nested_topology_test.dart +4 -4
  24. package/dart/test/harness_phase_timeout_test.dart +2 -2
  25. package/dart/test/local_sync_inert_test.dart +1 -1
  26. package/dart/test/parent_signer_recovery_test.dart +2 -2
  27. package/dart/test/sealing_client_test.dart +4 -3
  28. package/dart/test/session_bound_test.dart +8 -7
  29. package/dart/test/test_harness_test.dart +13 -12
  30. package/dart/test/vo_read_typing_test.dart +4 -3
  31. package/dart/test/watch_after_offer_stall_test.dart +4 -3
  32. package/dart/test/webview_bridge_test.dart +102 -5
  33. package/dart_types/CHANGELOG.md +5 -0
  34. package/dart_types/lib/nomos_types.dart +9 -0
  35. package/dart_types/lib/src/nomos_ref.dart +20 -0
  36. package/dart_types/lib/src/optional_ref.dart +85 -0
  37. package/dart_types/lib/src/sha256_digest.dart +41 -0
  38. package/dart_types/lib/src/versioned_nomos_ref.dart +81 -0
  39. package/dart_types/pubspec.yaml +1 -1
  40. package/dart_types/test/optional_ref_test.dart +44 -0
  41. package/dart_types/test/sha256_digest_test.dart +18 -0
  42. package/package.json +9 -5
  43. package/runtime/generated-application-host.js +5365 -1105
  44. package/src/aggregate.ts +18 -0
  45. package/src/application_composition.ts +6 -32
  46. package/src/attested_core.ts +6 -3
  47. package/src/birth_meter.ts +1 -0
  48. package/src/birth_meter_ensure.ts +28 -2
  49. package/src/births.ts +1 -1
  50. package/src/build_package.ts +162 -538
  51. package/src/business_birth.ts +19 -3
  52. package/src/canonical_json.ts +21 -0
  53. package/src/check_package_main.ts +73 -33
  54. package/src/clear_directive.ts +19 -8
  55. package/src/codegen_dart.ts +305 -22
  56. package/src/codegen_dart_application.ts +844 -292
  57. package/src/codegen_dart_client.ts +1084 -407
  58. package/src/codegen_dart_scenario.ts +12 -12
  59. package/src/codegen_proof.ts +169 -39
  60. package/src/codegen_provider_dart.ts +17 -1
  61. package/src/codegen_ts.ts +298 -106
  62. package/src/compat_manifest.ts +2 -2
  63. package/src/compat_package_main.ts +8 -12
  64. package/src/compile_package_main.ts +1858 -590
  65. package/src/compose.ts +1 -1
  66. package/src/directive.ts +208 -15
  67. package/src/engine_entry.ts +165 -111
  68. package/src/evolve_preview.ts +29 -69
  69. package/src/extremum.ts +1 -1
  70. package/src/fields.ts +183 -4
  71. package/src/flow_gate.ts +75 -2
  72. package/src/framework/application_home.ts +2 -0
  73. package/src/framework/auth_provider_law.ts +2 -2
  74. package/src/framework/birth_meter.ts +7 -19
  75. package/src/framework/bootstrap.ts +0 -2
  76. package/src/framework/business_corrections.ts +9 -5
  77. package/src/framework/domain_lifecycle.ts +15 -29
  78. package/src/framework/encryption_scope.ts +2 -1
  79. package/src/framework/framework_aggregates.ts +2 -0
  80. package/src/framework/genesis.ts +16 -14
  81. package/src/framework/home.ts +20 -14
  82. package/src/framework/owned_custody.ts +9 -3
  83. package/src/framework/platform_admin.ts +3 -3
  84. package/src/framework/relations.ts +21 -13
  85. package/src/framework/signing_identity.ts +45 -40
  86. package/src/framework/workspace_invariant.ts +245 -0
  87. package/src/framework/workspaces.ts +23 -29
  88. package/src/index.ts +36 -16
  89. package/src/intent.ts +178 -6
  90. package/src/law_check.ts +32 -11
  91. package/src/law_graph.ts +2902 -0
  92. package/src/law_graph_usda.ts +1799 -0
  93. package/src/law_identity.ts +435 -0
  94. package/src/law_value_type.ts +230 -0
  95. package/src/lsp_server.ts +58 -29
  96. package/src/ops.ts +7 -0
  97. package/src/package_config.ts +141 -0
  98. package/src/package_dependencies.ts +108 -0
  99. package/src/package_dependency_usage.ts +150 -0
  100. package/src/package_source_imports.ts +71 -0
  101. package/src/plan_source_slice.ts +335 -0
  102. package/src/point_guard.ts +192 -0
  103. package/src/precondition.ts +44 -9
  104. package/src/read_projection_namespace.ts +1 -1
  105. package/src/runtime_zod.ts +44 -0
  106. package/src/secondary_ensure.ts +67 -14
  107. package/src/shape_compat.ts +1 -1
  108. package/src/stable_id_identity_bridge.ts +149 -0
  109. package/src/stable_id_lockfile.ts +140 -6
  110. package/src/stable_ids.ts +1 -1
  111. package/src/stable_ids_for_module.ts +348 -0
  112. package/src/stable_ids_types.ts +1 -1
  113. package/src/sum.ts +1 -1
  114. package/src/usd_state.ts +1 -1
  115. package/src/usda_relationship_integrity.ts +66 -0
  116. package/src/usda_text.ts +18 -0
  117. package/src/usdz.ts +78 -0
  118. package/src/value_object.ts +95 -0
  119. package/src/wire.ts +19 -0
  120. package/src/wire_encode.ts +22 -0
  121. package/src/workspace_sharding.ts +52 -36
  122. package/src/workspace_sharing.ts +28 -4
  123. package/src/zod_introspection.ts +1 -1
  124. package/dart/test/cluster_attested_test.dart +0 -201
  125. package/src/compile_engine.ts +0 -595
  126. package/src/manifest.ts +0 -1476
  127. package/src/read_projection_composition.ts +0 -117
  128. package/src/read_projection_manifest.ts +0 -115
  129. package/src/relation_composition.ts +0 -286
  130. package/src/usd.ts +0 -1967
  131. package/src/usd_layers.ts +0 -1776
@@ -13,14 +13,54 @@
13
13
  // Resolution goes through Node's resolver (createRequire), NOT node_modules/.bin
14
14
  // paths — hoisted/workspace installs put the bin shims elsewhere.
15
15
  import { execFileSync } from "node:child_process";
16
- import { readFileSync } from "node:fs";
16
+ import { existsSync, readFileSync } from "node:fs";
17
17
  import { createRequire } from "node:module";
18
18
  import path from "node:path";
19
19
  import { fileURLToPath, pathToFileURL } from "node:url";
20
+ import {
21
+ compileInputs,
22
+ compileProofPath,
23
+ readCompileProof,
24
+ } from "./compile_proof.mjs";
20
25
 
21
26
  const DSL_DIR = path.dirname(fileURLToPath(import.meta.url));
22
27
  const MAIN = path.join(DSL_DIR, "src", "compile_package_main.ts");
23
28
 
29
+ const args = process.argv.slice(2);
30
+ const configArg = args.find((argument) => !argument.startsWith("--")) ?? "nomos.project.ts";
31
+ const configPath = path.resolve(process.cwd(), configArg);
32
+ const cacheable =
33
+ existsSync(configPath) &&
34
+ !args.includes("--preflight") &&
35
+ !args.includes("--analyze") &&
36
+ process.env.NOMOS_PREFLIGHT !== "1" &&
37
+ process.env.NOMOS_ANALYZE !== "1";
38
+ const argumentIdentity = [
39
+ ...args,
40
+ `NOMOS_COMPACT=${process.env.NOMOS_COMPACT ?? ""}`,
41
+ `NOMOS_REQUIRE_USDCAT=${process.env.NOMOS_REQUIRE_USDCAT ?? ""}`,
42
+ `NOMOS_USDCAT=${process.env.NOMOS_USDCAT ?? ""}`,
43
+ ].join("\n");
44
+ if (cacheable) {
45
+ const proofPath = compileProofPath(process.cwd(), configPath);
46
+ const inputs = compileInputs({
47
+ cwd: process.cwd(),
48
+ dslDir: DSL_DIR,
49
+ configPath,
50
+ argumentIdentity,
51
+ });
52
+ const proof = readCompileProof({ proofPath, inputs });
53
+ if (proof !== undefined) {
54
+ console.log(`nomos-compile: ${proof.name} unchanged`);
55
+ console.log(` law ${path.relative(process.cwd(), proof.law)}`);
56
+ console.log(` domainHash ${proof.domainHash}`);
57
+ console.log(` verify ✓ typed USDA content proof covers compiler, authored inputs and ${proof.outputCount} generated artifacts`);
58
+ process.exit(0);
59
+ }
60
+ process.env.NOMOS_COMPILE_PROOF_PATH = proofPath;
61
+ process.env.NOMOS_COMPILE_ARGUMENT_IDENTITY = argumentIdentity;
62
+ }
63
+
24
64
  /** Resolve a dependency's package dir from `fromDir`, walking Node's resolver. */
25
65
  function resolvePkgDir(name, fromDir) {
26
66
  try {
@@ -41,9 +81,10 @@ const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.tsx;
41
81
  const tsxCli = path.join(tsxDir, tsxBinRel ?? "dist/cli.mjs");
42
82
 
43
83
  try {
44
- execFileSync(process.execPath, [tsxCli, MAIN, ...process.argv.slice(2)], {
84
+ execFileSync(process.execPath, [tsxCli, MAIN, ...args], {
45
85
  stdio: "inherit",
46
86
  cwd: process.cwd(),
87
+ env: process.env,
47
88
  });
48
89
  } catch (e) {
49
90
  process.exit(e.status ?? 1);
@@ -0,0 +1,47 @@
1
+ export interface CompileProofInputs {
2
+ readonly authoring: readonly { readonly path: string; readonly sha256: string }[];
3
+ readonly compiler: readonly { readonly path: string; readonly sha256: string }[];
4
+ readonly authoringIdentity: string;
5
+ readonly compilerIdentity: string;
6
+ readonly argumentIdentity: string;
7
+ }
8
+
9
+ export function compileInputs(options: {
10
+ cwd: string;
11
+ dslDir: string;
12
+ configPath: string;
13
+ argumentIdentity: string;
14
+ }): CompileProofInputs;
15
+ export function compileProofPath(cwd: string, configPath: string): string;
16
+ export function generatedOutputFiles(
17
+ outDir: string,
18
+ additional?: readonly string[],
19
+ ): readonly { readonly path: string; readonly sha256: string }[];
20
+ export function writeCompileProof(options: {
21
+ proofPath: string;
22
+ inputs: CompileProofInputs;
23
+ outputs: readonly { readonly path: string; readonly sha256: string }[];
24
+ name: string;
25
+ domainHash: string;
26
+ law: string;
27
+ }): void;
28
+ export function readCompileProof(options: {
29
+ proofPath: string;
30
+ inputs: CompileProofInputs;
31
+ }): { name: string; domainHash: string; law: string; outputCount: number } | undefined;
32
+ export function writePlanCompileProof(options: {
33
+ proofPath: string;
34
+ baseIdentity: string;
35
+ runtimeSha256: string;
36
+ plan: string;
37
+ planSha256: string;
38
+ inputs: readonly { readonly path: string; readonly sha256: string }[];
39
+ }): void;
40
+ export function readPlanCompileProof(options: {
41
+ proofPath: string;
42
+ baseIdentity: string;
43
+ runtimeSha256: string;
44
+ digestFile?: (file: string) => string;
45
+ }): { javascript: string; sha256: string } | undefined;
46
+ export function writeKeyProofUsda(file: string, format: string, key: string): void;
47
+ export function readKeyProofUsda(file: string, format: string): string | undefined;
@@ -0,0 +1,343 @@
1
+ // A content-addressed compiler proof expressed as USDA, not a parallel JSON manifest.
2
+ // It is disposable build cache metadata under node_modules/.cache: law and custody
3
+ // remain the emitted typed USDA closure.
4
+ import { createHash } from "node:crypto";
5
+ import {
6
+ existsSync,
7
+ mkdirSync,
8
+ readFileSync,
9
+ readdirSync,
10
+ renameSync,
11
+ statSync,
12
+ writeFileSync,
13
+ } from "node:fs";
14
+ import { createRequire } from "node:module";
15
+ import path from "node:path";
16
+ import { pathToFileURL } from "node:url";
17
+
18
+ const INPUT_EXTENSIONS = new Set([
19
+ ".ts", ".mts", ".cts", ".js", ".mjs", ".cjs", ".json", ".yaml", ".yml",
20
+ ]);
21
+ const EXCLUDED_DIRECTORIES = new Set([
22
+ ".dart_tool", ".git", ".nomos-cache", "coverage", "node_modules",
23
+ ]);
24
+ const HASH = /^[0-9a-f]{64}$/u;
25
+
26
+ const compareText = (left, right) => left < right ? -1 : left > right ? 1 : 0;
27
+ const sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex");
28
+ const usdaString = (value) => `"${String(value)
29
+ .replaceAll("\\", "\\\\")
30
+ .replaceAll("\"", "\\\"")
31
+ .replaceAll("\n", "\\n")
32
+ .replaceAll("\r", "\\r")}"`;
33
+
34
+ function walk(root, predicate, { excludeDefaultBuild = false } = {}) {
35
+ const files = [];
36
+ const visit = (directory) => {
37
+ let entries;
38
+ try {
39
+ entries = readdirSync(directory, { withFileTypes: true });
40
+ } catch {
41
+ return;
42
+ }
43
+ for (const entry of entries) {
44
+ if (entry.isSymbolicLink()) continue;
45
+ if (entry.isDirectory()) {
46
+ if (EXCLUDED_DIRECTORIES.has(entry.name)) continue;
47
+ if (excludeDefaultBuild && entry.name === "build" && directory === root) continue;
48
+ visit(path.join(directory, entry.name));
49
+ } else if (entry.isFile()) {
50
+ const file = path.join(directory, entry.name);
51
+ if (predicate(file)) files.push(file);
52
+ }
53
+ }
54
+ };
55
+ visit(path.resolve(root));
56
+ return files;
57
+ }
58
+
59
+ function inventory(files) {
60
+ return [...new Set(files.map((file) => path.resolve(file)))]
61
+ .sort(compareText)
62
+ .map((file) => ({ path: file, sha256: existsSync(file) ? sha256(readFileSync(file)) : "missing" }));
63
+ }
64
+
65
+ function inventoryIdentity(kind, entries) {
66
+ const hash = createHash("sha256").update(`nomos-compile-${kind}-v1\0`);
67
+ for (const entry of entries) hash.update(entry.path).update("\0").update(entry.sha256).update("\0");
68
+ return hash.digest("hex");
69
+ }
70
+
71
+ function dependencyPackageFiles(dslDir, cwd) {
72
+ const files = [];
73
+ for (const name of ["esbuild", "tsx", "typescript", "zod"]) {
74
+ for (const base of [cwd, dslDir]) {
75
+ try {
76
+ const request = createRequire(pathToFileURL(path.join(base, "noop.js")));
77
+ files.push(request.resolve(`${name}/package.json`));
78
+ break;
79
+ } catch {
80
+ // The real compiler names a missing dependency after a proof miss.
81
+ }
82
+ }
83
+ }
84
+ return files;
85
+ }
86
+
87
+ export function compileInputs({ cwd, dslDir, configPath, argumentIdentity }) {
88
+ const authoring = inventory([
89
+ configPath,
90
+ ...walk(cwd, (file) => INPUT_EXTENSIONS.has(path.extname(file)), { excludeDefaultBuild: true }),
91
+ ]);
92
+ const compiler = inventory([
93
+ ...walk(path.join(dslDir, "src"), (file) => INPUT_EXTENSIONS.has(path.extname(file))),
94
+ ...walk(path.join(dslDir, "runtime"), (file) => INPUT_EXTENSIONS.has(path.extname(file))),
95
+ path.join(dslDir, "package.json"),
96
+ path.join(dslDir, "compile_package.mjs"),
97
+ path.join(dslDir, "compile_proof.mjs"),
98
+ ...dependencyPackageFiles(dslDir, cwd),
99
+ ]);
100
+ return {
101
+ authoring,
102
+ compiler,
103
+ authoringIdentity: inventoryIdentity("authoring", authoring),
104
+ compilerIdentity: inventoryIdentity("implementation", compiler),
105
+ argumentIdentity: sha256(`nomos-compile-arguments-v1\0${argumentIdentity}`),
106
+ };
107
+ }
108
+
109
+ export function compileProofPath(cwd, configPath) {
110
+ const key = sha256(path.resolve(configPath)).slice(0, 24);
111
+ return path.join(cwd, "node_modules", ".cache", "nomos", `${key}.compile-proof.usda`);
112
+ }
113
+
114
+ function artifactPrim(kind, entry, proofDir) {
115
+ const id = sha256(`${kind}\0${entry.path}`).slice(0, 24);
116
+ const relative = path.relative(proofDir, entry.path).replaceAll(path.sep, "/");
117
+ const type = kind === "input" ? "NomosCompileInput" : "NomosCompileArtifact";
118
+ return {
119
+ id: `${kind[0]}_${id}`,
120
+ lines: [
121
+ ` def ${type} "${kind[0]}_${id}"`,
122
+ " {",
123
+ ` custom uniform asset nomos:path = @${relative}@`,
124
+ ` custom uniform string nomos:sha256 = "${entry.sha256}"`,
125
+ " }",
126
+ ],
127
+ };
128
+ }
129
+
130
+ function emitCompileProof({ proofPath, inputs, outputs, name, domainHash, law }) {
131
+ const proofDir = path.dirname(proofPath);
132
+ const inputPrims = [...inputs.authoring, ...inputs.compiler].map((entry) => artifactPrim("input", entry, proofDir));
133
+ const outputPrims = outputs.map((entry) => artifactPrim("output", entry, proofDir));
134
+ const relationships = (scope, prims) => prims.map((prim) => ` </CompileProof/${scope}/${prim.id}>`);
135
+ return [
136
+ "#usda 1.0",
137
+ "(",
138
+ " customLayerData = {",
139
+ ' string "nomos:format" = "nomos.compile-proof.v1"',
140
+ " }",
141
+ ")",
142
+ "",
143
+ 'def NomosCompileProof "CompileProof"',
144
+ "{",
145
+ ` custom uniform string nomos:package = ${usdaString(name)}`,
146
+ ` custom uniform string nomos:domainHash = "${domainHash}"`,
147
+ ` custom uniform asset nomos:law = @${path.relative(proofDir, law).replaceAll(path.sep, "/")}@`,
148
+ ` custom uniform string nomos:authoringIdentity = "${inputs.authoringIdentity}"`,
149
+ ` custom uniform string nomos:compilerIdentity = "${inputs.compilerIdentity}"`,
150
+ ` custom uniform string nomos:argumentIdentity = "${inputs.argumentIdentity}"`,
151
+ " custom rel nomos:inputs = [",
152
+ ...relationships("Inputs", inputPrims).map((line, index) => `${line}${index + 1 === inputPrims.length ? "" : ","}`),
153
+ " ]",
154
+ " custom rel nomos:outputs = [",
155
+ ...relationships("Outputs", outputPrims).map((line, index) => `${line}${index + 1 === outputPrims.length ? "" : ","}`),
156
+ " ]",
157
+ "",
158
+ ' def Scope "Inputs"',
159
+ " {",
160
+ ...inputPrims.flatMap((prim) => [...prim.lines, ""]),
161
+ " }",
162
+ "",
163
+ ' def Scope "Outputs"',
164
+ " {",
165
+ ...outputPrims.flatMap((prim) => [...prim.lines, ""]),
166
+ " }",
167
+ "}",
168
+ "",
169
+ ].join("\n");
170
+ }
171
+
172
+ export function generatedOutputFiles(outDir, additional = []) {
173
+ return inventory([
174
+ ...walk(outDir, (file) => {
175
+ const name = path.basename(file);
176
+ return !file.split(path.sep).some((segment) => segment.includes(".nomos-bak")) &&
177
+ !name.startsWith(".nomos_") &&
178
+ !name.startsWith(".nomos-mountability-proof.");
179
+ }),
180
+ ...additional,
181
+ ]);
182
+ }
183
+
184
+ export function writeCompileProof({ proofPath, inputs, outputs, name, domainHash, law }) {
185
+ if (!HASH.test(domainHash) || outputs.some((entry) => !HASH.test(entry.sha256))) {
186
+ throw new Error("compile proof requires content-addressed law and generated artifacts");
187
+ }
188
+ mkdirSync(path.dirname(proofPath), { recursive: true });
189
+ const temporary = `${proofPath}.tmp-${process.pid}`;
190
+ writeFileSync(temporary, emitCompileProof({ proofPath, inputs, outputs, name, domainHash, law }), "utf8");
191
+ renameSync(temporary, proofPath);
192
+ }
193
+
194
+ function property(text, name) {
195
+ const match = new RegExp(`custom uniform string nomos:${name} = "([0-9a-f]{64})"`, "u").exec(text);
196
+ return match?.[1];
197
+ }
198
+
199
+ function proofOutputs(text, proofPath) {
200
+ const outputsScope = /def Scope "Outputs"\s*\{([\s\S]*)\n \}/u.exec(text)?.[1];
201
+ if (outputsScope === undefined) return undefined;
202
+ const entries = [];
203
+ const pattern = /def NomosCompileArtifact "[^"]+"\s*\{\s*custom uniform asset nomos:path = @([^@]+)@\s*custom uniform string nomos:sha256 = "([0-9a-f]{64})"\s*\}/gu;
204
+ for (const match of outputsScope.matchAll(pattern)) {
205
+ entries.push({ path: path.resolve(path.dirname(proofPath), match[1]), sha256: match[2] });
206
+ }
207
+ return entries.length === 0 ? undefined : entries;
208
+ }
209
+
210
+ export function readCompileProof({ proofPath, inputs }) {
211
+ let text;
212
+ try {
213
+ text = readFileSync(proofPath, "utf8");
214
+ } catch {
215
+ return undefined;
216
+ }
217
+ if (!text.includes('string "nomos:format" = "nomos.compile-proof.v1"')) return undefined;
218
+ if (
219
+ property(text, "authoringIdentity") !== inputs.authoringIdentity ||
220
+ property(text, "compilerIdentity") !== inputs.compilerIdentity ||
221
+ property(text, "argumentIdentity") !== inputs.argumentIdentity
222
+ ) return undefined;
223
+ const outputs = proofOutputs(text, proofPath);
224
+ if (outputs === undefined) return undefined;
225
+ for (const output of outputs) {
226
+ if (!existsSync(output.path) || !statSync(output.path).isFile()) return undefined;
227
+ if (sha256(readFileSync(output.path)) !== output.sha256) return undefined;
228
+ }
229
+ const packageMatch = /custom uniform string nomos:package = "([^"\\]*)"/u.exec(text);
230
+ const domainHash = property(text, "domainHash");
231
+ const lawMatch = /custom uniform asset nomos:law = @([^@]+)@/u.exec(text);
232
+ if (packageMatch === null || domainHash === undefined || lawMatch === null) return undefined;
233
+ return {
234
+ name: packageMatch[1],
235
+ domainHash,
236
+ law: path.resolve(path.dirname(proofPath), lawMatch[1]),
237
+ outputCount: outputs.length,
238
+ };
239
+ }
240
+
241
+ function emitPlanCompileProof({ proofPath, baseIdentity, runtimeSha256, plan, planSha256, inputs }) {
242
+ const proofDir = path.dirname(proofPath);
243
+ const inputPrims = inputs.map((entry) => artifactPrim("input", entry, proofDir));
244
+ return [
245
+ "#usda 1.0",
246
+ "(",
247
+ " customLayerData = {",
248
+ ' string "nomos:format" = "nomos.plan-compile-proof.v1"',
249
+ " }",
250
+ ")",
251
+ "",
252
+ 'def NomosPlanCompileProof "PlanCompileProof"',
253
+ "{",
254
+ ` custom uniform string nomos:baseIdentity = "${baseIdentity}"`,
255
+ ` custom uniform string nomos:runtimeSha256 = "${runtimeSha256}"`,
256
+ ` custom uniform asset nomos:plan = @${path.relative(proofDir, plan).replaceAll(path.sep, "/")}@`,
257
+ ` custom uniform string nomos:planSha256 = "${planSha256}"`,
258
+ " custom rel nomos:inputs = [",
259
+ ...inputPrims.map((prim, index) =>
260
+ ` </PlanCompileProof/Inputs/${prim.id}>${index + 1 === inputPrims.length ? "" : ","}`),
261
+ " ]",
262
+ "",
263
+ ' def Scope "Inputs"',
264
+ " {",
265
+ ...inputPrims.flatMap((prim) => [...prim.lines, ""]),
266
+ " }",
267
+ "}",
268
+ "",
269
+ ].join("\n");
270
+ }
271
+
272
+ export function writePlanCompileProof({ proofPath, baseIdentity, runtimeSha256, plan, planSha256, inputs }) {
273
+ if (![baseIdentity, runtimeSha256, planSha256, ...inputs.map((entry) => entry.sha256)].every((value) => HASH.test(value))) {
274
+ throw new Error("plan compile proof requires content-addressed identities");
275
+ }
276
+ mkdirSync(path.dirname(proofPath), { recursive: true });
277
+ const temporary = `${proofPath}.tmp-${process.pid}`;
278
+ writeFileSync(
279
+ temporary,
280
+ emitPlanCompileProof({ proofPath, baseIdentity, runtimeSha256, plan, planSha256, inputs }),
281
+ "utf8",
282
+ );
283
+ renameSync(temporary, proofPath);
284
+ }
285
+
286
+ export function readPlanCompileProof({ proofPath, baseIdentity, runtimeSha256, digestFile }) {
287
+ let text;
288
+ try {
289
+ text = readFileSync(proofPath, "utf8");
290
+ } catch {
291
+ return undefined;
292
+ }
293
+ if (!text.includes('string "nomos:format" = "nomos.plan-compile-proof.v1"')) return undefined;
294
+ if (property(text, "baseIdentity") !== baseIdentity || property(text, "runtimeSha256") !== runtimeSha256) {
295
+ return undefined;
296
+ }
297
+ const inputsScope = /def Scope "Inputs"\s*\{([\s\S]*)\n \}/u.exec(text)?.[1];
298
+ if (inputsScope === undefined) return undefined;
299
+ const inputs = [];
300
+ const inputPattern = /def NomosCompileInput "[^"]+"\s*\{\s*custom uniform asset nomos:path = @([^@]+)@\s*custom uniform string nomos:sha256 = "([0-9a-f]{64})"\s*\}/gu;
301
+ for (const match of inputsScope.matchAll(inputPattern)) {
302
+ inputs.push({ path: path.resolve(path.dirname(proofPath), match[1]), sha256: match[2] });
303
+ }
304
+ if (inputs.length === 0) return undefined;
305
+ for (const input of inputs) {
306
+ if (!existsSync(input.path) || (digestFile ?? ((file) => sha256(readFileSync(file))))(input.path) !== input.sha256) {
307
+ return undefined;
308
+ }
309
+ }
310
+ const planMatch = /custom uniform asset nomos:plan = @([^@]+)@/u.exec(text);
311
+ const planSha256 = property(text, "planSha256");
312
+ if (planMatch === null || planSha256 === undefined) return undefined;
313
+ const plan = path.resolve(path.dirname(proofPath), planMatch[1]);
314
+ if (!existsSync(plan)) return undefined;
315
+ const javascript = readFileSync(plan, "utf8");
316
+ if (sha256(javascript) !== planSha256) return undefined;
317
+ return { javascript, sha256: planSha256 };
318
+ }
319
+
320
+ export function writeKeyProofUsda(file, format, key) {
321
+ if (!HASH.test(key)) throw new Error(`invalid ${format} proof identity`);
322
+ const text = [
323
+ "#usda 1.0",
324
+ "(",
325
+ " customLayerData = {",
326
+ ` string "nomos:format" = ${usdaString(format)}`,
327
+ ` string "nomos:proofIdentity" = "${key}"`,
328
+ " }",
329
+ ")",
330
+ "",
331
+ ].join("\n");
332
+ writeFileSync(file, text, "utf8");
333
+ }
334
+
335
+ export function readKeyProofUsda(file, format) {
336
+ try {
337
+ const text = readFileSync(file, "utf8");
338
+ if (!text.includes(`string "nomos:format" = ${usdaString(format)}`)) return undefined;
339
+ return /string "nomos:proofIdentity" = "([0-9a-f]{64})"/u.exec(text)?.[1];
340
+ } catch {
341
+ return undefined;
342
+ }
343
+ }
package/dart/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.64.2
2
+
3
+ - Execute generated applications through the typed USDA-native kernel boundary, including native read
4
+ recipes, sealed offer diagnostics and lawful self-serve birth retries after typed kernel refusals.
5
+ - Remove the legacy JSON deployment and bridge paths so tenant type errors continue to originate at the
6
+ kernel boundary used in production.
7
+
1
8
  ## 0.64.1
2
9
 
3
10
  - Resolve a compiled OpenUSD application as one ordered package set in generated offline and connected
@@ -5,7 +5,7 @@
5
5
  //
6
6
  // ```dart
7
7
  // final cloud = await NomosTestCloud.start(serverEntry: devServerPath); // spawns the dev cloud + proxy
8
- // final harness = await NomosTestHarness.cloudBound(cloud: cloud, deployJsonPaths: [...], platformWorkspace: 'co2-platform', subject: 'user:test');
8
+ // final harness = await NomosTestHarness.cloudBound(cloud: cloud, lawUsdzPaths: [...], platformWorkspace: 'co2-platform', subject: 'user:test');
9
9
  // // ... author offline ...
10
10
  // cloud.setOnline(false); // PARTITION — the up leg can't reach custody
11
11
  // await harness.session('estate').sync(admit: true); // stays local; nothing lands remotely
@@ -118,14 +118,14 @@ class NomosTestCloud {
118
118
  /// (the old lane — the harness POST-creating the platform — refuses 409 `unborn` by design).
119
119
  String? platform,
120
120
 
121
- /// Optional single platform law to deploy at boot. Prefer [deployJsonPaths] for a composed application.
122
- String? deployJsonPath,
121
+ /// Optional single platform law to deploy at boot. Prefer [lawUsdzPaths] for a composed application.
122
+ String? lawUsdzPath,
123
123
 
124
124
  /// Ordered application package set installed by the warranted bootstrap operator before serving.
125
125
  /// Reference-only/control packages go first and remain active on the parent; the home payload package
126
126
  /// goes last and is retained as the explicit law used to birth a receiving group. A payload package is
127
127
  /// not made current on the parent merely to make it available to a child.
128
- List<String> deployJsonPaths = const [],
128
+ List<String> lawUsdzPaths = const [],
129
129
  Duration readyTimeout = const Duration(seconds: 30),
130
130
  void Function(String line)? onDiagnostic,
131
131
  }) async {
@@ -138,10 +138,10 @@ class NomosTestCloud {
138
138
  if (dataDir != null) ...['--data', dataDir],
139
139
  if (platform != null) ...['--platform', platform],
140
140
  for (final deploy in [
141
- ...deployJsonPaths,
142
- if (deployJsonPath != null && !deployJsonPaths.contains(deployJsonPath))
143
- deployJsonPath,
144
- ]) ...['--deploy', deploy],
141
+ ...lawUsdzPaths,
142
+ if (lawUsdzPath != null && !lawUsdzPaths.contains(lawUsdzPath))
143
+ lawUsdzPath,
144
+ ]) ...['--law', deploy],
145
145
  ];
146
146
  void log(String m) => onDiagnostic?.call('[nomos-test-cloud] $m');
147
147
  log('spawning: $node ${args.join(' ')}');
@@ -8,6 +8,8 @@ import 'package:meta/meta.dart' show internal;
8
8
 
9
9
  export 'package:nomos_types/nomos_types.dart';
10
10
  export 'package:nomos_types/src/nomos_ref.dart' show NmsInternalNomosRefs;
11
+ export 'package:nomos_types/src/versioned_nomos_ref.dart'
12
+ show NmsInternalVersionedNomosRefs;
11
13
  export 'package:nomos_types/src/invitation.dart'
12
14
  show NmsInternalInvitations, NmsInternalRecipients, NmsInternalUsers;
13
15
  export 'package:nomos_types/src/foreign_ref.dart'