use std::collections::BTreeMap;
use std::fs;
use std::path::Path;
use xchecker::redaction::{default_pattern_defs, doc_gen};
const BEGIN_MARKER: &str = "<!-- BEGIN GENERATED:DEFAULT_SECRET_PATTERNS -->";
const END_MARKER: &str = "<!-- END GENERATED:DEFAULT_SECRET_PATTERNS -->";
fn replace_generated_block(content: &str, body: &str) -> Result<String, String> {
let begin_pos = content
.find(BEGIN_MARKER)
.ok_or_else(|| format!("Missing begin marker: {}", BEGIN_MARKER))?;
let end_pos = content
.find(END_MARKER)
.ok_or_else(|| format!("Missing end marker: {}", END_MARKER))?;
if end_pos < begin_pos {
return Err("End marker appears before begin marker".to_string());
}
let mut out = String::new();
out.push_str(&content[..begin_pos + BEGIN_MARKER.len()]);
out.push('\n');
out.push_str(body);
out.push_str(&content[end_pos..]);
Ok(out)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Regenerating secret patterns documentation...\n");
let security_doc_path = Path::new("docs/explanation/SECURITY_MODEL.md");
if !security_doc_path.exists() {
return Err(format!("File not found: {}", security_doc_path.display()).into());
}
let current_content = doc_gen::normalize_line_endings(&fs::read_to_string(security_doc_path)?);
let patterns = default_pattern_defs();
let generated_markdown = doc_gen::render_patterns_markdown(patterns);
let new_content = replace_generated_block(¤t_content, &generated_markdown)?;
if current_content == new_content {
println!("✓ docs/explanation/SECURITY_MODEL.md is already up-to-date");
println!("\nPattern summary:");
} else {
fs::write(security_doc_path, &new_content)?;
println!("✓ Updated docs/explanation/SECURITY_MODEL.md");
println!("\nPattern summary:");
}
let mut by_category: BTreeMap<&str, usize> = BTreeMap::new();
for p in patterns {
*by_category.entry(p.category).or_default() += 1;
}
for (category, count) in &by_category {
println!(" - {}: {} patterns", category, count);
}
println!(
" Total: {} patterns across {} categories",
patterns.len(),
by_category.len()
);
println!("\n✅ Secret patterns documentation is in sync with code!");
Ok(())
}