feat(config-source): add confined read-only builtin Decodal imports

Share the explicit embedded Profile catalog with native and WASM evaluators. Preserve ordinary Decodal values, isolate builtin relative imports, reject reserved Workspace mutations, and capture the exact loaded builtin closure. Guard lazy import cycles and dependency depth before evaluation recurses.

Validation: config-source 48 tests, builtin-source 2 tests, manifest 185 tests; root cargo check, formatting and diff checks pass. Existing contract version/fingerprint stay unchanged; archive provenance binds builtin content instead of invalidating stored Workspace metadata.
This commit is contained in:
2026-10-07 03:35:59 +09:00
parent a64707ee69
commit 4343be86c1
9 changed files with 721 additions and 211 deletions
+41
View File
@@ -0,0 +1,41 @@
use builtin_source::{BUILTIN_PROFILE_RESOURCES, builtin_profile_catalog_snapshot};
use std::collections::BTreeSet;
#[test]
fn public_catalog_is_closed_and_explicit() {
let catalog = builtin_profile_catalog_snapshot();
assert_eq!(catalog.sources.len(), BUILTIN_PROFILE_RESOURCES.len());
assert!(catalog.digest().starts_with("sha256:"));
for resource in BUILTIN_PROFILE_RESOURCES {
assert!(resource.path.starts_with("profiles/"));
assert!(resource.path.ends_with(".dcdl"));
assert_eq!(catalog.sources[resource.path], resource.source);
for import in resource.imports {
assert!(catalog.sources.contains_key(import.resolved_path));
assert!(
resource
.source
.contains(&format!("import {:?}", import.specifier))
);
}
}
assert!(!catalog.sources.contains_key("prompts/default.md"));
}
#[test]
fn catalog_import_metadata_has_no_cycles() {
fn visit(path: &str, visiting: &mut BTreeSet<String>) {
assert!(visiting.insert(path.to_string()), "catalog cycle at {path}");
let resource = BUILTIN_PROFILE_RESOURCES
.iter()
.find(|resource| resource.path == path)
.unwrap();
for import in resource.imports {
visit(import.resolved_path, visiting);
}
visiting.remove(path);
}
for resource in BUILTIN_PROFILE_RESOURCES {
visit(resource.path, &mut BTreeSet::new());
}
}