1pub const NOT_AUTHORIZED_PREFIX: &str = "not authorized:";
8
9pub fn not_authorized(msg: &str) -> String {
11 format!("{NOT_AUTHORIZED_PREFIX} {msg}")
12}
13
14pub fn is_not_authorized(text: &str) -> bool {
18 let t = text.trim_start();
19 let t = t.strip_prefix("Error:").map(str::trim_start).unwrap_or(t);
20 t.len() >= NOT_AUTHORIZED_PREFIX.len()
21 && t[..NOT_AUTHORIZED_PREFIX.len()].eq_ignore_ascii_case(NOT_AUTHORIZED_PREFIX)
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27
28 #[test]
29 fn refusals_are_recognised_with_or_without_the_mcp_wrapper() {
30 assert!(is_not_authorized(¬_authorized(
31 "target 'ghost' for parallel_jobs"
32 )));
33 assert!(is_not_authorized("Error: not authorized: fleet_run denied"));
34 assert!(is_not_authorized(" NOT AUTHORIZED: x"));
35 assert!(
36 !is_not_authorized("the file says: not authorized: nope"),
37 "prefix, not substring"
38 );
39 assert!(!is_not_authorized("permission denied"));
40 }
41}