//! `recall` and `memory` in `brokerd`: their arguments, the built-in grants that allow them in //! every session, and grant files that name them refused (M5a spec, section 8). Do not edit. #[path = "support/build.rs"] mod build; #[path = "support/tmp.rs"] mod tmp; use brokerd::args::{ToolArgs, ToolName, parse}; use brokerd::builtin::{BUILT_IN, MEMORY, RECALL}; use brokerd::grants::{GrantSet, load}; use brokerd::policy::{Label, Outcome, decide}; use build::{allowed, grant, now, private, request, secret, set}; use bxcore::{DataClass, DenyReason, Mode, sha256}; use tmp::TempDir; #[test] fn the_names_and_arguments_of_the_memory_tools() { assert_eq!(ToolName::parse("recall"), Some(ToolName::Recall)); assert_eq!(ToolName::parse("memory"), Some(ToolName::Memory)); assert_eq!( (ToolName::Recall.as_str(), ToolName::Memory.as_str()), ("recall", "memory") ); assert!(ToolName::Recall.is_memory() && ToolName::Memory.is_memory()); assert!( ToolName::ALL.iter().all(|t| !t.is_memory()), "ALL is the container tools" ); let recall = parse(ToolName::Recall, r#"{ "k": 3, "query": "launch" }"#).unwrap(); assert_eq!(recall.tool(), ToolName::Recall); assert_eq!(recall.canonical_json(), r#"{"query":"launch","k":3}"#); let memory = parse(ToolName::Memory, r#"{"text":"x","action":"note"}"#).unwrap(); assert!(matches!(memory, ToolArgs::Memory(_))); assert_eq!(memory.canonical_json(), r#"{"action":"note","text":"x"}"#); for (tool, bad) in [ (ToolName::Recall, r#"{"query":""}"#), (ToolName::Recall, r#"{"query":"x","k":11}"#), ( ToolName::Memory, r#"{"action":"add","file":"soul","text":"x"}"#, ), ( ToolName::Memory, r#"{"action":"add","file":"memory","text":"a\n§\nb"}"#, ), ( ToolName::Memory, r#"{"action":"consolidate","file":"memory","entries":[]}"#, ), ] { assert!(parse(tool, bad).is_err(), "{bad}"); } } #[test] fn both_are_allowed_in_every_session_by_the_built_in_grants() { let grants = set(vec![]); for state in [private(), secret()] { let d = allowed(decide( request("recall", r#"{"query":"x"}"#), &grants, state, now(), )); assert_eq!(d.grant(), "builtin-recall"); assert_eq!(d.grant_sha256(), sha256(RECALL.as_bytes()).unwrap()); assert_eq!( d.label(), Label { class: DataClass::Private, untrusted: false } ); let d = allowed(decide( request("memory", r#"{"action":"note","text":"x"}"#), &grants, state, now(), )); assert_eq!(d.grant(), "builtin-memory"); assert_eq!(d.grant_sha256(), sha256(MEMORY.as_bytes()).unwrap()); } } #[test] fn a_set_without_built_ins_has_no_memory_tools() { let outcome = decide( request("recall", r#"{"query":"x"}"#), &GrantSet::default(), private(), now(), ); assert!( matches!(outcome, Outcome::Denied(ref d) if d.reason == DenyReason::NoGrant), "{outcome:?}" ); } #[test] fn grant_files_cannot_name_the_memory_tools_or_take_a_built_in_id() { let dir = TempDir::new("memory-grants"); std::fs::write( dir.path().join("mine.toml"), "tool = \"memory\"\nmode = \"ask\"\nmax_taint = \"secret\"\n", ) .unwrap(); std::fs::write( dir.path().join("off.toml"), "tool = \"recall\"\nmode = \"deny\"\nmax_taint = \"secret\"\n", ) .unwrap(); std::fs::write( dir.path().join("builtin-x.toml"), "tool = \"shell\"\nmode = \"ask\"\nmax_taint = \"private\"\n", ) .unwrap(); let problems = load(dir.path()).unwrap_err(); let got: Vec<(String, String)> = problems.into_iter().map(|p| (p.file, p.problem)).collect(); assert!( got.contains(&("mine.toml".to_string(), BUILT_IN.to_string())), "{got:?}" ); assert!( got.contains(&("off.toml".to_string(), BUILT_IN.to_string())), "{got:?}" ); assert!( got.contains(&( "builtin-x.toml".to_string(), "grant ids starting builtin- are reserved".to_string() )), "{got:?}" ); let with_shell = set(vec![grant("s", "shell", Mode::Ask)]); assert_eq!( with_shell.grants().len(), 1, "the built-ins are not listed as the owner's" ); assert_eq!(with_shell.matchable().count(), 3); }