package_boundary.rs (10198B)
1 use std::collections::BTreeSet; 2 3 const MANIFEST: &str = include_str!("../Cargo.toml"); 4 const README: &str = include_str!("../README"); 5 const PUBLIC_API: &str = 6 include_str!("../../../contracts/api_baselines/radroots_runtime_paths.txt"); 7 const ROOT: &str = include_str!("../src/lib.rs"); 8 const SOURCES: &[&str] = &[ 9 include_str!("../src/context.rs"), 10 include_str!("../src/conventions.rs"), 11 include_str!("../src/error.rs"), 12 include_str!("../src/identifier.rs"), 13 include_str!("../src/platform.rs"), 14 include_str!("../src/provision.rs"), 15 include_str!("../src/roots.rs"), 16 include_str!("../src/service.rs"), 17 ]; 18 19 #[test] 20 fn runtime_paths_is_unpublished_lint_governed_and_dependency_bounded() { 21 for required in [ 22 "name = \"radroots_runtime_paths\"", 23 "publish = false", 24 "version = \"0.1.0-alpha\"", 25 ] { 26 assert!( 27 MANIFEST.contains(required), 28 "manifest is missing `{required}`" 29 ); 30 } 31 assert_eq!( 32 dependency_keys(MANIFEST), 33 BTreeSet::from(["rustix", "serde", "thiserror"]) 34 ); 35 assert_eq!( 36 ROOT.lines() 37 .filter_map(|line| line.strip_prefix("mod ")) 38 .filter_map(|line| line.strip_suffix(';')) 39 .collect::<BTreeSet<_>>(), 40 BTreeSet::from([ 41 "context", 42 "conventions", 43 "error", 44 "identifier", 45 "platform", 46 "provision", 47 "roots", 48 "service", 49 ]) 50 ); 51 assert!(!ROOT.contains("pub mod ")); 52 assert!(ROOT.contains("#![doc = include_str!(\"../README\")]")); 53 for source in SOURCES { 54 let production = source.split("#[cfg(test)]").next().unwrap_or(source); 55 assert!(!production.contains("std::env")); 56 for forbidden in [ 57 "impl Into<String>", 58 "let value = value.into();", 59 "String::deserialize", 60 ] { 61 assert!( 62 !production.contains(forbidden), 63 "bounded runtime-path text boundary still contains `{forbidden}`" 64 ); 65 } 66 } 67 assert!( 68 SOURCES 69 .iter() 70 .any(|source| source.contains("deserializer.deserialize_str(Visitor)")) 71 ); 72 } 73 74 #[test] 75 fn removed_namespace_selection_and_raw_root_surfaces_cannot_return() { 76 for forbidden in [ 77 "RadrootsRuntimeNamespace", 78 "RadrootsRuntimeNamespaceKind", 79 "RadrootsServiceInstanceNamespace", 80 "RadrootsRuntimePathSelection", 81 "RadrootsRuntimePathConfigEntry", 82 "RadrootsRuntimePathPolicyContract", 83 "RadrootsRuntimeSelectionContract", 84 "RadrootsRuntimeSelectionOverrideContract", 85 "RadrootsPathOverrides", 86 "RadrootsBootstrapPaths", 87 "default_service_instance_paths", 88 "default_namespaced_bootstrap_paths", 89 "default_shared_identity_path", 90 "default_shared_runtime_logs_dir", 91 "from_current_process", 92 "MissingMobileRoots", 93 "InvalidNamespaceComponent", 94 ] { 95 assert!( 96 SOURCES.iter().all(|source| !source.contains(forbidden)) && !ROOT.contains(forbidden), 97 "removed runtime-path surface `{forbidden}` returned" 98 ); 99 } 100 101 for forbidden in [ 102 "pub struct radroots_runtime_paths::RadrootsPaths", 103 "pub struct radroots_runtime_paths::RadrootsPathOverrides", 104 "pub struct radroots_runtime_paths::RadrootsRuntimeNamespace", 105 "pub struct radroots_runtime_paths::RadrootsServiceInstanceNamespace", 106 "pub struct radroots_runtime_paths::RadrootsRuntimePathSelection", 107 "pub fn radroots_runtime_paths::RadrootsPathResolver::current", 108 "pub fn radroots_runtime_paths::RadrootsPathResolver::resolve", 109 ] { 110 assert!( 111 !PUBLIC_API.contains(forbidden), 112 "reviewed API baseline exposes `{forbidden}`" 113 ); 114 } 115 } 116 117 #[test] 118 fn reviewed_api_requires_the_typed_runtime_context_boundary() { 119 for required in [ 120 "pub struct radroots_runtime_paths::RuntimeContext", 121 "pub struct radroots_runtime_paths::RuntimeContextBootstrap", 122 "pub enum radroots_runtime_paths::RuntimeContextSource", 123 "pub struct radroots_runtime_paths::RadrootsPathResolver", 124 "pub struct radroots_runtime_paths::RadrootsServiceInstancePaths", 125 "pub struct radroots_runtime_paths::RadrootsServiceInstanceArtifacts", 126 "pub struct radroots_runtime_paths::ServiceId", 127 "pub struct radroots_runtime_paths::InstanceId", 128 "pub fn radroots_runtime_paths::RuntimeContext::resolve", 129 "pub fn radroots_runtime_paths::RuntimeContext::repo_local_root", 130 "pub fn radroots_runtime_paths::RuntimeContext::state_directory_plan", 131 "pub struct radroots_runtime_paths::RuntimeStateDirectoryPlan", 132 "pub fn radroots_runtime_paths::RuntimeStateDirectoryPlan::provision", 133 "pub enum radroots_runtime_paths::StateDirectoryProvisionError", 134 "pub fn radroots_runtime_paths::RadrootsPlatform::current", 135 "pub fn radroots_runtime_paths::default_service_instance_artifacts", 136 "pub fn radroots_runtime_paths::service_credential_artifact_path", 137 "pub fn radroots_runtime_paths::default_shared_geonames_database_path_from_cache_root", 138 "pub fn radroots_runtime_paths::default_shared_runtime_store_database_path_from_data_root", 139 ] { 140 assert!( 141 PUBLIC_API.contains(required), 142 "reviewed API baseline is missing `{required}`" 143 ); 144 } 145 146 for required in [ 147 "## Example", 148 "## Root Profiles", 149 "## State Directory Provisioning", 150 "## Common Artifacts", 151 "## Support Caveats", 152 "## Public API Baseline", 153 "The final reviewed root-only API", 154 "validated as\n borrowed UTF-8 before the crate creates their retained strings", 155 "```rust", 156 "| Linux `ServiceHost` | `/etc/radroots` | `/var/lib/radroots` | `/var/cache/radroots` | `/var/log/radroots` | `/run/radroots` | `/etc/radroots/secrets` |", 157 "| Linux `InteractiveUser` | `$XDG_CONFIG_HOME/radroots` | `$XDG_DATA_HOME/radroots` | `$XDG_CACHE_HOME/radroots` | `$XDG_STATE_HOME/radroots/logs` | `$XDG_RUNTIME_DIR/radroots` | `$XDG_CONFIG_HOME/radroots/secrets` |", 158 "| macOS `InteractiveUser` | `$HOME/Library/Application Support/Radroots/config` | `$HOME/Library/Application Support/Radroots/data` | `$HOME/Library/Caches/Radroots` | `$HOME/Library/Logs/Radroots` | `$HOME/Library/Application Support/Radroots/run` | `$HOME/Library/Application Support/Radroots/secrets` |", 159 r"| Windows `InteractiveUser` | `%APPDATA%\Radroots\config` | `%LOCALAPPDATA%\Radroots\data` | `%LOCALAPPDATA%\Radroots\cache` | `%LOCALAPPDATA%\Radroots\logs` | `%LOCALAPPDATA%\Radroots\run` | `%APPDATA%\Radroots\secrets` |", 160 "| `RepoLocal` | `<base>/config` | `<base>/data` | `<base>/cache` | `<base>/logs` | `<base>/run` | `<base>/secrets` |", 161 "| Configuration | `<config>/config.toml` |", 162 "| SQLite state | `<state>/state.sqlite` |", 163 "| SQLite writer lock | `<state>/state.lock` |", 164 "| Local admin socket | `<run>/admin.sock` |", 165 "| Credential artifact | `<secrets>/<validated-credential-name>` |", 166 "Pure path\nresolution never reads the ambient process environment or performs filesystem\nI/O.", 167 "create only `services/<service>/<instance>`, one descriptor-relative component", 168 "never changes an existing mode, and identity-checks any cleanup", 169 "An entry whose identity cannot\nbe proven is preserved and the operation fails closed.", 170 "For `ServiceHost`, the entire state-directory suffix must already exist.", 171 "stable path-free unsupported-platform classification", 172 "does not create any common\nartifact, configuration, cache, log, run, or secrets path", 173 "An absolute\n`XDG_RUNTIME_DIR` is mandatory and has no fallback.", 174 "Linux service-host\non x86_64 and aarch64 is eligible for Tier 1 only after all release gates pass.", 175 "Linux and macOS interactive and explicit repo-local profiles on x86_64 and\naarch64 are developer-target behavior.", 176 "Linux rootless OCI on x86_64 and\naarch64 is also only a target", 177 "Windows interactive and repo-local derivation is\nimplemented but unsupported and carries no v1 support claim.", 178 "Non-Linux `ServiceHost`, `MobileNative`, Android/iOS/Other interactive,", 179 "Repo-local never", 180 "Successful compilation or path derivation does not change", 181 "[runtime-paths API baseline](../../contracts/api_baselines/radroots_runtime_paths.txt)", 182 ] { 183 assert!(README.contains(required), "README is missing `{required}`"); 184 } 185 186 for forbidden in [ 187 "pub mod radroots_runtime_paths::context", 188 "pub mod radroots_runtime_paths::conventions", 189 "pub mod radroots_runtime_paths::error", 190 "pub mod radroots_runtime_paths::identifier", 191 "pub mod radroots_runtime_paths::platform", 192 "pub mod radroots_runtime_paths::provision", 193 "pub mod radroots_runtime_paths::roots", 194 "pub mod radroots_runtime_paths::service", 195 "radroots_runtime_paths::context::", 196 "radroots_runtime_paths::conventions::", 197 "radroots_runtime_paths::error::", 198 "radroots_runtime_paths::identifier::", 199 "radroots_runtime_paths::platform::", 200 "radroots_runtime_paths::provision::", 201 "radroots_runtime_paths::roots::", 202 "radroots_runtime_paths::service::", 203 "thiserror::", 204 "serde_json::", 205 "rustix::", 206 ] { 207 assert!( 208 !PUBLIC_API.contains(forbidden), 209 "reviewed API baseline exposes `{forbidden}`" 210 ); 211 } 212 } 213 214 fn dependency_keys(manifest: &str) -> BTreeSet<&str> { 215 manifest 216 .split_once("[dependencies]") 217 .map(|(_, dependencies)| dependencies) 218 .unwrap_or_default() 219 .lines() 220 .skip(1) 221 .take_while(|line| !line.starts_with('[')) 222 .filter_map(|line| line.split_once('=').map(|(key, _)| key.trim())) 223 .filter(|key| !key.is_empty()) 224 .collect() 225 }