use super::*;
use crate::tools::chosen_path::make_link;
#[test]
fn a_link_is_judged_by_where_it_lands() {
let dir = tempfile::tempdir().unwrap();
let outside = tempfile::tempdir().unwrap();
for room in ["lab", "vault/room1", ".sprawling"] {
std::fs::create_dir_all(dir.path().join(room)).unwrap();
}
std::fs::write(dir.path().join("vault/room1/secret.md"), "the vault\n").unwrap();
std::fs::write(dir.path().join(".sprawling/secret.md"), "governance\n").unwrap();
std::fs::write(outside.path().join("secret.md"), "elsewhere\n").unwrap();
let lab = dir.path().join("lab");
make_link(
&lab.join("to-vault"),
&dir.path().join("vault").join("room1"),
);
make_link(&lab.join("to-reserved"), &dir.path().join(".sprawling"));
make_link(&lab.join("to-outside"), outside.path());
let only_lab: ReadBound = Arc::new(|addr: &kernel::Address| {
if addr.as_str().starts_with("vault") {
kernel::ReadVerdict::Confidential
} else {
kernel::ReadVerdict::Open
}
});
let catalog = Arc::new(Mutex::new(Catalog::new()));
let tool = ReadTool::new(dir.path(), catalog, only_lab, Path::new("no-store")).unwrap();
for asked in [
"lab/to-vault/secret.md",
"lab/to-reserved/secret.md",
"lab/to-outside/secret.md",
"lab/to-vault/absent.md",
"lab/to-outside/absent.md",
] {
let refused = tool.invoke(&call(asked));
assert!(
matches!(&refused, Err(err) if err.code() == &AxCode::GateDenied),
"{asked} was read through a link: {refused:?}"
);
}
}
#[test]
fn a_package_the_reading_room_admits_opens_by_name_and_path() {
let dir = tempfile::tempdir().unwrap();
let package = dir.path().join(".sprawling").join("library").join("review");
std::fs::create_dir_all(package.join("scripts")).unwrap();
std::fs::write(package.join("SKILL.md"), "check the diff first\n").unwrap();
std::fs::write(package.join("scripts").join("check.sh"), "git diff\n").unwrap();
std::fs::write(dir.path().join(".sprawling").join("CONFIG.toml"), "x\n").unwrap();
let (tool, catalog) = tool(dir.path());
catalog
.lock()
.unwrap()
.admit_skill(CatalogEntry {
name: "review".to_owned(),
disclosure: "how this building reviews".to_owned(),
expansion: ".sprawling/library/review/SKILL.md".to_owned(),
hash: None,
package: Some(".sprawling/library/review".to_owned()),
})
.unwrap();
make_link(&package.join("out"), &dir.path().join(".sprawling"));
let outcome = tool.invoke(&call("review/scripts/check.sh")).unwrap();
assert_eq!(outcome.result.as_map()["text"], "git diff\n");
for (leaving, code) in [
("review/out/CONFIG.toml", AxCode::GateDenied),
("review/out/absent.md", AxCode::GateDenied),
("review/../../CONFIG.toml", AxCode::InvalidArgs),
("review/./SKILL.md", AxCode::InvalidArgs),
("review/", AxCode::InvalidArgs),
] {
let err = tool.invoke(&call(leaving)).unwrap_err();
assert_eq!(err.code(), &code, "{leaving} was opened");
}
let miss = tool.invoke(&call("review/scriptz/check.sh")).unwrap_err();
assert_eq!(
miss.nearby(),
["review/SKILL.md", "review/out", "review/scripts"],
"a miss in a package offers the package's entries as the caller names them"
);
}
#[test]
fn a_shelved_document_behind_a_link_is_refused() {
let dir = tempfile::tempdir().unwrap();
let outside = tempfile::tempdir().unwrap();
std::fs::write(outside.path().join("SKILL.md"), "elsewhere\n").unwrap();
let library = dir.path().join(".sprawling").join("library");
std::fs::create_dir_all(library.join("kept")).unwrap();
std::fs::write(library.join("kept").join("SKILL.md"), "on the shelf\n").unwrap();
make_link(&library.join("notes"), outside.path());
let (tool, catalog) = tool(dir.path());
for name in ["kept", "notes"] {
catalog
.lock()
.unwrap()
.admit_skill(CatalogEntry {
name: name.to_owned(),
disclosure: format!("the {name} skill"),
expansion: format!(".sprawling/library/{name}/SKILL.md"),
hash: None,
package: None,
})
.unwrap();
}
let kept = tool.invoke(&call("kept")).unwrap();
assert_eq!(kept.result.as_map()["text"], "on the shelf\n");
let refused = tool.invoke(&call("notes"));
assert!(
matches!(&refused, Err(err) if err.code() == &AxCode::GateDenied),
"a shelved document was read through a link: {refused:?}"
);
}
#[test]
fn a_file_absent_at_the_check_is_not_opened_later() {
let dir = tempfile::tempdir().unwrap();
for room in ["lab", "annex", "vault/room1"] {
std::fs::create_dir_all(dir.path().join(room)).unwrap();
}
std::fs::write(dir.path().join("vault/room1/secret.md"), "the vault\n").unwrap();
make_link(
&dir.path().join("lab").join("door"),
&dir.path().join("annex"),
);
let root = dir.path().to_path_buf();
let between: ReadBound = Arc::new(move |addr: &kernel::Address| {
let placed = root.join("annex").join("sub");
if addr.as_str().starts_with("annex/") && !placed.exists() {
make_link(&placed, &root.join("vault").join("room1"));
}
if addr.as_str().starts_with("vault") {
kernel::ReadVerdict::Confidential
} else {
kernel::ReadVerdict::Open
}
});
let tool = ReadTool::new(
dir.path(),
Arc::new(Mutex::new(Catalog::new())),
between,
Path::new("no-store"),
)
.unwrap();
let refused = tool.invoke(&call("lab/door/sub/secret.md"));
assert!(
matches!(&refused, Err(err) if err.code() == &AxCode::InvalidArgs),
"a file absent at the check was opened through a link placed after it: {refused:?}"
);
}
#[test]
fn a_directory_swapped_for_a_link_after_the_check_opens_nothing() {
let dir = tempfile::tempdir().unwrap();
for room in ["lab", "annex/sub", "vault/room1"] {
std::fs::create_dir_all(dir.path().join(room)).unwrap();
}
std::fs::write(dir.path().join("annex/sub/secret.md"), "the annex\n").unwrap();
std::fs::write(dir.path().join("vault/room1/secret.md"), "the vault\n").unwrap();
make_link(
&dir.path().join("lab").join("door"),
&dir.path().join("annex"),
);
let root = dir.path().to_path_buf();
let between: ReadBound = Arc::new(move |addr: &kernel::Address| {
let checked = root.join("annex").join("sub");
if addr.as_str() == "annex/sub/secret.md" && !checked.is_symlink() {
std::fs::remove_dir_all(&checked).unwrap();
make_link(&checked, &root.join("vault").join("room1"));
}
if addr.as_str().starts_with("vault") {
kernel::ReadVerdict::Confidential
} else {
kernel::ReadVerdict::Open
}
});
let tool = ReadTool::new(
dir.path(),
Arc::new(Mutex::new(Catalog::new())),
between,
Path::new("no-store"),
)
.unwrap();
let refused = tool.invoke(&call("lab/door/sub/secret.md"));
assert!(
matches!(&refused, Err(err) if err.code() == &AxCode::GateDenied),
"a file was read through a link swapped in after the check: {refused:?}"
);
}
#[test]
fn a_document_named_like_a_package_opens_nothing_beside_it() {
let dir = tempfile::tempdir().unwrap();
let section = dir.path().join(".sprawling").join("library").join("ops");
std::fs::create_dir_all(§ion).unwrap();
std::fs::write(section.join("SKILL.md"), "how ops works\n").unwrap();
std::fs::write(section.join("deploy.md"), "not admitted\n").unwrap();
let (tool, catalog) = tool(dir.path());
catalog
.lock()
.unwrap()
.admit_skill(CatalogEntry {
name: "SKILL".to_owned(),
disclosure: "how ops works".to_owned(),
expansion: ".sprawling/library/ops/SKILL.md".to_owned(),
hash: None,
package: None,
})
.unwrap();
let refused = tool.invoke(&call("SKILL/deploy.md"));
assert!(
refused.is_err(),
"a skill the reading room did not admit was read beside a document: {refused:?}"
);
}