use std::io::IsTerminal;
#[must_use]
pub fn authenticate(rule: &str, message: &str) -> bool {
if !std::io::stderr().is_terminal() {
return false;
}
#[cfg(target_os = "macos")]
{
macos_touch_id(rule, message)
}
#[cfg(not(target_os = "macos"))]
{
let _ = (rule, message);
false
}
}
#[cfg(target_os = "macos")]
fn macos_touch_id(rule: &str, message: &str) -> bool {
eprintln!(
"\x1b[33m⚡ guardrail [{rule}]: {message}\x1b[0m"
);
eprintln!(
"\x1b[36m🔐 Touch ID to override, or press Cancel to block\x1b[0m"
);
let swift_code = format!(
r#"
import LocalAuthentication
import Foundation
let context = LAContext()
var error: NSError?
guard context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) else {{
exit(1)
}}
let semaphore = DispatchSemaphore(value: 0)
var success = false
context.evaluatePolicy(
.deviceOwnerAuthentication,
localizedReason: "guardrail [{rule}]: {message}"
) {{ result, _ in
success = result
semaphore.signal()
}}
semaphore.wait()
exit(success ? 0 : 1)
"#
);
let result = std::process::Command::new("/usr/bin/swift")
.args(["-e", &swift_code])
.stdin(std::process::Stdio::inherit())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::inherit())
.status();
match result {
Ok(status) => {
if status.success() {
eprintln!("\x1b[32m✅ Biometric bypass granted for [{rule}]\x1b[0m");
true
} else {
eprintln!("\x1b[31m❌ Bypass denied — command blocked\x1b[0m");
false
}
}
Err(e) => {
eprintln!("guardrail: biometric auth unavailable: {e}");
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn non_interactive_always_denies() {
assert!(!authenticate("test-rule", "test message"));
}
#[test]
fn authenticate_returns_bool() {
let _: bool = authenticate("rule", "msg");
}
}