@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.
- package/compile_package.mjs +43 -2
- package/compile_proof.d.mts +47 -0
- package/compile_proof.mjs +343 -0
- package/dart/CHANGELOG.md +7 -0
- package/dart/lib/src/dev_cloud.dart +8 -8
- package/dart/lib/src/nms_generated_runtime.dart +2 -0
- package/dart/lib/src/runner/node-entry.mjs +5504 -1236
- package/dart/lib/src/runner/offline-install.mjs +4578 -528
- package/dart/lib/src/test_harness.dart +206 -152
- package/dart/lib/src/webview_bridge.dart +196 -89
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +2 -2
- package/dart/test/acquire_session_credentials_test.dart +4 -3
- package/dart/test/adv_realm_interference_test.dart +7 -6
- package/dart/test/cloud_bound_topology_test.dart +3 -3
- package/dart/test/cluster_births_test.dart +4 -3
- package/dart/test/cluster_device_keyed_acceptance_test.dart +10 -16
- package/dart/test/cluster_local_autosync_test.dart +3 -2
- package/dart/test/cluster_scale_test.dart +3 -2
- package/dart/test/dlq_session_surface_test.dart +7 -6
- package/dart/test/first_app_gauntlet_test.dart +14 -21
- package/dart/test/fixtures/wedge/fake-install.mjs +1 -1
- package/dart/test/four_layer_nested_topology_test.dart +4 -4
- package/dart/test/harness_phase_timeout_test.dart +2 -2
- package/dart/test/local_sync_inert_test.dart +1 -1
- package/dart/test/parent_signer_recovery_test.dart +2 -2
- package/dart/test/sealing_client_test.dart +4 -3
- package/dart/test/session_bound_test.dart +8 -7
- package/dart/test/test_harness_test.dart +13 -12
- package/dart/test/vo_read_typing_test.dart +4 -3
- package/dart/test/watch_after_offer_stall_test.dart +4 -3
- package/dart/test/webview_bridge_test.dart +102 -5
- package/dart_types/CHANGELOG.md +5 -0
- package/dart_types/lib/nomos_types.dart +9 -0
- package/dart_types/lib/src/nomos_ref.dart +20 -0
- package/dart_types/lib/src/optional_ref.dart +85 -0
- package/dart_types/lib/src/sha256_digest.dart +41 -0
- package/dart_types/lib/src/versioned_nomos_ref.dart +81 -0
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/optional_ref_test.dart +44 -0
- package/dart_types/test/sha256_digest_test.dart +18 -0
- package/package.json +9 -5
- package/runtime/generated-application-host.js +5365 -1105
- package/src/aggregate.ts +18 -0
- package/src/application_composition.ts +6 -32
- package/src/attested_core.ts +6 -3
- package/src/birth_meter.ts +1 -0
- package/src/birth_meter_ensure.ts +28 -2
- package/src/births.ts +1 -1
- package/src/build_package.ts +162 -538
- package/src/business_birth.ts +19 -3
- package/src/canonical_json.ts +21 -0
- package/src/check_package_main.ts +73 -33
- package/src/clear_directive.ts +19 -8
- package/src/codegen_dart.ts +305 -22
- package/src/codegen_dart_application.ts +844 -292
- package/src/codegen_dart_client.ts +1084 -407
- package/src/codegen_dart_scenario.ts +12 -12
- package/src/codegen_proof.ts +169 -39
- package/src/codegen_provider_dart.ts +17 -1
- package/src/codegen_ts.ts +298 -106
- package/src/compat_manifest.ts +2 -2
- package/src/compat_package_main.ts +8 -12
- package/src/compile_package_main.ts +1858 -590
- package/src/compose.ts +1 -1
- package/src/directive.ts +208 -15
- package/src/engine_entry.ts +165 -111
- package/src/evolve_preview.ts +29 -69
- package/src/extremum.ts +1 -1
- package/src/fields.ts +183 -4
- package/src/flow_gate.ts +75 -2
- package/src/framework/application_home.ts +2 -0
- package/src/framework/auth_provider_law.ts +2 -2
- package/src/framework/birth_meter.ts +7 -19
- package/src/framework/bootstrap.ts +0 -2
- package/src/framework/business_corrections.ts +9 -5
- package/src/framework/domain_lifecycle.ts +15 -29
- package/src/framework/encryption_scope.ts +2 -1
- package/src/framework/framework_aggregates.ts +2 -0
- package/src/framework/genesis.ts +16 -14
- package/src/framework/home.ts +20 -14
- package/src/framework/owned_custody.ts +9 -3
- package/src/framework/platform_admin.ts +3 -3
- package/src/framework/relations.ts +21 -13
- package/src/framework/signing_identity.ts +45 -40
- package/src/framework/workspace_invariant.ts +245 -0
- package/src/framework/workspaces.ts +23 -29
- package/src/index.ts +36 -16
- package/src/intent.ts +178 -6
- package/src/law_check.ts +32 -11
- package/src/law_graph.ts +2902 -0
- package/src/law_graph_usda.ts +1799 -0
- package/src/law_identity.ts +435 -0
- package/src/law_value_type.ts +230 -0
- package/src/lsp_server.ts +58 -29
- package/src/ops.ts +7 -0
- package/src/package_config.ts +141 -0
- package/src/package_dependencies.ts +108 -0
- package/src/package_dependency_usage.ts +150 -0
- package/src/package_source_imports.ts +71 -0
- package/src/plan_source_slice.ts +335 -0
- package/src/point_guard.ts +192 -0
- package/src/precondition.ts +44 -9
- package/src/read_projection_namespace.ts +1 -1
- package/src/runtime_zod.ts +44 -0
- package/src/secondary_ensure.ts +67 -14
- package/src/shape_compat.ts +1 -1
- package/src/stable_id_identity_bridge.ts +149 -0
- package/src/stable_id_lockfile.ts +140 -6
- package/src/stable_ids.ts +1 -1
- package/src/stable_ids_for_module.ts +348 -0
- package/src/stable_ids_types.ts +1 -1
- package/src/sum.ts +1 -1
- package/src/usd_state.ts +1 -1
- package/src/usda_relationship_integrity.ts +66 -0
- package/src/usda_text.ts +18 -0
- package/src/usdz.ts +78 -0
- package/src/value_object.ts +95 -0
- package/src/wire.ts +19 -0
- package/src/wire_encode.ts +22 -0
- package/src/workspace_sharding.ts +52 -36
- package/src/workspace_sharing.ts +28 -4
- package/src/zod_introspection.ts +1 -1
- package/dart/test/cluster_attested_test.dart +0 -201
- package/src/compile_engine.ts +0 -595
- package/src/manifest.ts +0 -1476
- package/src/read_projection_composition.ts +0 -117
- package/src/read_projection_manifest.ts +0 -115
- package/src/relation_composition.ts +0 -286
- package/src/usd.ts +0 -1967
- package/src/usd_layers.ts +0 -1776
package/compile_package.mjs
CHANGED
|
@@ -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, ...
|
|
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,
|
|
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 [
|
|
122
|
-
String?
|
|
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>
|
|
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
|
-
...
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
]) ...['--
|
|
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'
|