Seven task files for the implementing model under docs/plans/M1/, with the test files, byte-exact fixtures, Makefile, deny.toml and gate-script self-test they copy into place. All of it was verified against a private reference implementation: the gate passes after every task in order. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
68 lines
2.0 KiB
Rust
68 lines
2.0 KiB
Rust
//! Tests for grant files. Do not edit these or the fixtures.
|
|
|
|
use proto::{Constraints, DataClass, Grant, Mode, Timestamp};
|
|
|
|
fn parse(name: &str) -> Result<Grant, toml::de::Error> {
|
|
let path = format!("{}/tests/fixtures/grant/{name}", env!("CARGO_MANIFEST_DIR"));
|
|
let text = std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("{path}: {e}"));
|
|
toml::from_str(&text)
|
|
}
|
|
|
|
#[test]
|
|
fn minimal_grant_gets_safe_defaults() {
|
|
let want = Grant {
|
|
tool: "read_file".to_string(),
|
|
mode: Mode::Auto,
|
|
max_taint: DataClass::Private,
|
|
result_class: DataClass::Private,
|
|
untrusted: true,
|
|
expires: None,
|
|
secret: None,
|
|
constraints: Constraints::default(),
|
|
};
|
|
assert_eq!(parse("minimal.toml").unwrap(), want);
|
|
assert_eq!(Constraints::default().paths, Vec::<String>::new());
|
|
}
|
|
|
|
#[test]
|
|
fn full_grant() {
|
|
let want = Grant {
|
|
tool: "http_fetch".to_string(),
|
|
mode: Mode::Ask,
|
|
max_taint: DataClass::Secret,
|
|
result_class: DataClass::Public,
|
|
untrusted: false,
|
|
expires: Some(Timestamp::parse("2026-12-31T00:00:00.000Z").unwrap()),
|
|
secret: Some("example-api-token".to_string()),
|
|
constraints: Constraints {
|
|
paths: vec!["/home/kyle/notes/**".to_string()],
|
|
hosts: vec!["example.com".to_string(), "api.example.com".to_string()],
|
|
patterns: vec!["^GET ".to_string()],
|
|
},
|
|
};
|
|
assert_eq!(parse("full.toml").unwrap(), want);
|
|
}
|
|
|
|
#[test]
|
|
fn mistakes_in_grant_files_are_errors() {
|
|
for name in [
|
|
"unknown_field.toml",
|
|
"unknown_constraint.toml",
|
|
"bad_mode.toml",
|
|
"missing_max_taint.toml",
|
|
] {
|
|
assert!(parse(name).is_err(), "{name} was accepted");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn modes_are_lowercase() {
|
|
for (mode, text) in [
|
|
(Mode::Auto, "auto"),
|
|
(Mode::Ask, "ask"),
|
|
(Mode::Deny, "deny"),
|
|
] {
|
|
assert_eq!(serde_json::to_string(&mode).unwrap(), format!("\"{text}\""));
|
|
}
|
|
}
|