bxctl: sanitize check shows which sanitizer rules a text breaks

Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
2026-09-27 19:08:42 -07:00
co-authored by ornith-1.5-35b-a3b
parent 648469cd67
commit 54f102bbe1
7 changed files with 723 additions and 3 deletions
+28 -1
View File
@@ -1,6 +1,6 @@
//! `bxctl`: the owner's chat client for `loopd`.
use std::io::{BufRead, BufReader, Write};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::{Path, PathBuf};
use std::process::ExitCode;
@@ -49,6 +49,7 @@ fn main() -> ExitCode {
reason,
} => exit(|| cmd_refuse(&admin_socket, approval, reason.as_deref())),
Command::GrantsCheck { admin_socket } => exit(|| cmd_grants_check(&admin_socket)),
Command::SanitizeCheck { text } => cmd_sanitize_check(text),
Command::Memory { socket, ask } => {
let mut out = std::io::stdout().lock();
match bxctl::memory::run(&socket, &ask, bxctl::memory::MEMORY_TIMEOUT, &mut out) {
@@ -108,6 +109,32 @@ fn cmd_grants_check(admin: &Path) -> Result<bool, AdminError> {
admin::cmd_grants_check(admin, &mut out)
}
// `bxctl sanitize check`: 0 when no rule fires, 1 when one does. A text that cannot be read (not
// UTF-8, like an argument that is not) or an answer that cannot be written is 2, so 1 always
// means a rule fired.
fn cmd_sanitize_check(text: Option<String>) -> ExitCode {
let text = match text {
Some(text) => text,
None => {
let mut text = String::new();
if let Err(e) = std::io::stdin().read_to_string(&mut text) {
eprintln!("bxctl: cannot read standard input: {e}");
return ExitCode::from(2);
}
text
}
};
let mut out = std::io::stdout().lock();
match bxctl::sanitize::run(&text, &mut out) {
Ok(false) => ExitCode::SUCCESS,
Ok(true) => ExitCode::from(1),
Err(e) => {
eprintln!("bxctl: cannot write the report: {e}");
ExitCode::from(2)
}
}
}
fn on_pending(opts: &ChatOptions) -> OnPending {
if opts.json {
OnPending::EventOnly