diff --git a/crates/memoryd/tests/honcho_ask_serve.rs b/crates/memoryd/tests/honcho_ask_serve.rs index a2995d4..f9b4509 100644 --- a/crates/memoryd/tests/honcho_ask_serve.rs +++ b/crates/memoryd/tests/honcho_ask_serve.rs @@ -60,6 +60,16 @@ impl Home { /// One call on `brokerd`'s socket and its answer, within 20 s; how long it took. fn call(socket: &Path, tool: &str, arguments: &str) -> (ToolResponse, Duration) { + call_at(socket, tool, arguments, DataClass::Private) +} + +/// `call`, with the session's class on the `MemoryCall`. +fn call_at( + socket: &Path, + tool: &str, + arguments: &str, + taint: DataClass, +) -> (ToolResponse, Duration) { let started = Instant::now(); let mut stream = UnixStream::connect(socket).unwrap(); stream @@ -76,7 +86,7 @@ fn call(socket: &Path, tool: &str, arguments: &str) -> (ToolResponse, Duration) tool: tool.to_string(), arguments: arguments.to_string(), }, - taint: DataClass::Private, + taint, untrusted: false, }), }; @@ -230,3 +240,29 @@ fn an_unknown_tool_is_refused() { "memoryd runs only recall, memory and ask_memory" ); } + +/// Spec 13: a `secret` session's question still reaches Honcho; only a question holding a secret +/// is refused. +#[test] +fn a_secret_session_still_asks_honcho() { + let fake = FakeHoncho::start(); + let home = Home::serve("ask-serve-secret", Some(&fake.url)); + let (content, class, untrusted) = result( + call_at( + &home.config.broker_socket(), + "ask_memory", + QUESTION, + DataClass::Secret, + ) + .0, + ); + assert!( + fake.requests().iter().any(|r| r.path.ends_with("/chat")), + "Honcho was not asked: {content}" + ); + assert!( + content.starts_with("[1] memory · own · private\n Based on what I found in memory, "), + "{content}" + ); + assert_eq!((class, untrusted), (DataClass::Private, false)); +} diff --git a/crates/memoryd/tests/honcho_recall_serve.rs b/crates/memoryd/tests/honcho_recall_serve.rs index b28bc25..000c016 100644 --- a/crates/memoryd/tests/honcho_recall_serve.rs +++ b/crates/memoryd/tests/honcho_recall_serve.rs @@ -71,6 +71,16 @@ impl Home { /// One call on `brokerd`'s socket and its answer, within 20 s; how long it took. fn call(socket: &Path, tool: &str, arguments: &str) -> (ToolResponse, Duration) { + call_at(socket, tool, arguments, DataClass::Private) +} + +/// `call`, with the session's class on the `MemoryCall`. +fn call_at( + socket: &Path, + tool: &str, + arguments: &str, + taint: DataClass, +) -> (ToolResponse, Duration) { let started = Instant::now(); let mut stream = UnixStream::connect(socket).unwrap(); stream @@ -87,7 +97,7 @@ fn call(socket: &Path, tool: &str, arguments: &str) -> (ToolResponse, Duration) tool: tool.to_string(), arguments: arguments.to_string(), }, - taint: DataClass::Private, + taint, untrusted: false, }), }; @@ -239,3 +249,24 @@ fn without_honcho_recall_answers_as_before() { lines.lock().unwrap() ); } + +/// Spec 13: a `secret` session's query still reaches Honcho; only a query holding a secret is +/// refused. +#[test] +fn a_secret_session_still_asks_honcho() { + let fake = FakeHoncho::start(); + let home = Home::new("recall-serve-secret", Some(&fake.url)); + let _lines = home.serve(); + let (content, class, untrusted) = result( + call_at( + &home.config.broker_socket(), + "recall", + r#"{"query":"tea","k":10}"#, + DataClass::Secret, + ) + .0, + ); + assert!(!reads(&fake).is_empty(), "Honcho was not asked: {content}"); + assert!(content.contains("tea"), "{content}"); + assert_eq!((class, untrusted), (DataClass::Private, true)); +}