use std::collections::{BTreeSet, VecDeque};
use std::path::{Path, PathBuf};
use std::process::Command;
const FORBIDDEN: &[&str] = &[
"ratatui",
"crossterm",
"axum",
"ammonia",
"tauri",
"reqwest",
"rusqlite",
"tokio",
"hyper",
"wry",
"webkit2gtk",
];
const FORBIDDEN_STD: &[&str] = &["fs", "net", "process", "env"];
fn workspace_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("newt-interaction has a parent workspace directory")
.to_path_buf()
}
fn normal_dependency_closure(package: &str) -> BTreeSet<String> {
let out = Command::new(env!("CARGO"))
.args([
"metadata",
"--format-version",
"1",
"--all-features",
"--manifest-path",
])
.arg(workspace_root().join("Cargo.toml"))
.output()
.expect("cargo metadata runs");
assert!(
out.status.success(),
"cargo metadata failed: {}",
String::from_utf8_lossy(&out.stderr)
);
let meta: serde_json::Value =
serde_json::from_slice(&out.stdout).expect("cargo metadata emits json");
let mut name_of = std::collections::BTreeMap::new();
for pkg in meta["packages"].as_array().into_iter().flatten() {
let (Some(id), Some(name)) = (pkg["id"].as_str(), pkg["name"].as_str()) else {
continue;
};
name_of.insert(id.to_string(), name.to_string());
}
let mut deps_of = std::collections::BTreeMap::new();
let nodes = meta["resolve"]["nodes"]
.as_array()
.expect("resolve.nodes is an array");
for node in nodes {
let id = node["id"].as_str().expect("node id").to_string();
let mut normal = Vec::new();
for dep in node["deps"].as_array().into_iter().flatten() {
let kinds = dep["dep_kinds"].as_array().cloned().unwrap_or_default();
if kinds
.iter()
.any(|k| k["kind"].is_null() || k["kind"] == "build")
{
normal.push(dep["pkg"].as_str().expect("dep pkg id").to_string());
}
}
deps_of.insert(id, normal);
}
let start = name_of
.iter()
.find(|(_, name)| name.as_str() == package)
.map(|(id, _)| id.clone())
.unwrap_or_else(|| panic!("{package} is not in the resolve graph"));
let mut seen = BTreeSet::new();
let mut queue = VecDeque::from([start]);
let mut visited = BTreeSet::new();
while let Some(id) = queue.pop_front() {
if !visited.insert(id.clone()) {
continue;
}
for dep in deps_of.get(&id).into_iter().flatten() {
if let Some(name) = name_of.get(dep) {
seen.insert(name.clone());
}
queue.push_back(dep.clone());
}
}
seen
}
fn violations(closure: &BTreeSet<String>) -> Vec<String> {
closure
.iter()
.filter(|name| FORBIDDEN.contains(&name.as_str()) || name.starts_with("newt-"))
.cloned()
.collect()
}
#[test]
fn the_protocol_crate_has_no_forbidden_dependency() {
let closure = normal_dependency_closure("newt-interaction");
assert!(
!closure.is_empty(),
"the closure came back empty — the walker found nothing to check"
);
let found = violations(&closure);
assert!(
found.is_empty(),
"newt-interaction reaches forbidden crates {found:?} — the inward \
layer must depend on none of them, and on no newt-* crate. Closure: \
{closure:?}"
);
}
#[test]
fn the_default_runtime_dependencies_are_exactly_three() {
let manifest =
std::fs::read_to_string(Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml"))
.expect("manifest");
let table = manifest
.split("[dependencies]")
.nth(1)
.expect("a [dependencies] table")
.split("\n[")
.next()
.expect("the table ends");
let mut declared: Vec<String> = Vec::new();
let mut optional: Vec<String> = Vec::new();
for line in table.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let Some((name, rest)) = line.split_once(['=', '.']) else {
continue;
};
let name = name.trim().to_string();
if rest.contains("optional = true") {
optional.push(name);
} else {
declared.push(name);
}
}
declared.sort();
assert_eq!(
declared,
vec![
"content-addressable".to_string(),
"serde".to_string(),
"thiserror".to_string()
],
"the inward layer's runtime dependencies changed. Anything new here \
ships to every consumer, including the wyvern tier; if it is a \
build-time convenience, mark it `optional = true` behind a feature."
);
optional.sort();
assert_eq!(
optional,
vec!["schemars".to_string(), "serde_json".to_string()],
"an optional dependency appeared or vanished — schema GENERATION is \
the only sanctioned reason for one (schemars, plus serde_json for \
the const tag schemas it emits). Neither is in the default build."
);
}
#[test]
fn the_guard_would_notice_a_forbidden_dependency() {
let closure = normal_dependency_closure("newt-core");
let found = violations(&closure);
assert!(
found.iter().any(|name| name == "crossterm"),
"the closure walker failed to see crossterm in newt-core — it cannot \
be trusted to see one in newt-interaction. Found: {found:?}"
);
}
#[path = "../../newt-core/tests/common/mod.rs"]
#[allow(dead_code)]
mod common;
fn ambient_authority(dir: &Path) -> Vec<String> {
let mut found = Vec::new();
common::for_each_production_line(&[dir.join("src")], &|_| false, &mut |path, code, raw| {
if let Some(hit) = ambient_hit(code) {
found.push(format!("{}: {} [{hit}]", path.display(), raw.trim()));
}
});
found
}
fn ambient_hit(code: &str) -> Option<&'static str> {
for module in FORBIDDEN_STD {
if code.contains(&format!("std::{module}")) {
return Some(module);
}
}
let tail = code.split("use std::").nth(1)?;
for module in FORBIDDEN_STD {
let mut rest = tail;
while let Some(at) = rest.find(module) {
let before_ok = at == 0
|| !rest[..at]
.chars()
.next_back()
.is_some_and(|c| c.is_alphanumeric() || c == '_');
let after_ok = rest[at + module.len()..]
.chars()
.next()
.is_none_or(|c| !(c.is_alphanumeric() || c == '_'));
if before_ok && after_ok {
return Some(module);
}
rest = &rest[at + module.len()..];
}
}
None
}
fn probe_crate(name: &str, source: &str) -> PathBuf {
let mut probe = std::env::temp_dir();
probe.push(format!(
"newt-interaction-guard-{name}-{}",
std::process::id()
));
let src = probe.join("src");
std::fs::create_dir_all(&src).expect("probe dir");
std::fs::write(src.join("lib.rs"), source).expect("probe file");
probe
}
#[test]
fn the_protocol_crate_touches_no_ambient_authority() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let mut scanned = 0usize;
common::for_each_production_line(&[root.join("src")], &|_| false, &mut |_, _, _| {
scanned += 1;
});
assert!(
scanned > 50,
"the source scan saw only {scanned} lines — it is not reading this crate"
);
let found = ambient_authority(root);
assert!(
found.is_empty(),
"newt-interaction takes ambient authority: {found:#?}\nThe protocol \
layer describes records; reading a file, opening a socket, spawning \
a process, or consulting the environment all belong outward."
);
}
#[test]
fn the_source_scanner_sees_past_a_test_module() {
let probe = probe_crate(
"mid-file-cfg",
"#[cfg(test)]\nmod tests {\n fn t() { let _ = 1; }\n}\n\n\
pub fn real() -> String { std::fs::read_to_string(\"/etc/hostname\").unwrap() }\n",
);
let found = ambient_authority(&probe);
std::fs::remove_dir_all(&probe).ok();
assert_eq!(
found.len(),
1,
"production code after a test module went unscanned: {found:?}"
);
}
#[test]
fn the_source_scanner_sees_grouped_and_aliased_imports() {
for (name, source) in [
(
"group",
"use std::{env, fs};\npub fn f() -> bool { true }\n",
),
(
"alias",
"use std::fs as filesystem;\npub fn f() -> bool { true }\n",
),
(
"nested-group",
"use std::{collections::BTreeMap, process::Command};\npub fn f() -> bool { true }\n",
),
] {
let probe = probe_crate(name, source);
let found = ambient_authority(&probe);
std::fs::remove_dir_all(&probe).ok();
assert!(
!found.is_empty(),
"the `{name}` spelling of an ambient-authority import was missed"
);
}
}
#[test]
fn the_source_scanner_would_notice_ambient_authority() {
let probe = probe_crate(
"plain",
"pub fn read() -> String { std::fs::read_to_string(\"/etc/hostname\").unwrap() }\n",
);
let found = ambient_authority(&probe);
std::fs::remove_dir_all(&probe).ok();
assert_eq!(
found.len(),
1,
"the source scanner missed a std::fs call it was pointed straight at"
);
}