//! Regex patterns backing the deterministic (rule-based) guardrail layer. //! //! These are a fast, cheap first line of defense -- they catch the //! obvious cases before the query or draft ever reaches an LLM call, and //! they log independently of whatever the policy-compliance agent decides, //! so a policy-agent mistake doesn't silently erase the finding. use regex::Regex; pub struct NamedPattern { pub rule_id: &'static str, pub regex: Regex, } /// Heuristics for prompt-injection / instruction-override attempts. pub fn injection_patterns() -> Vec { build(&[ ("injection.ignore_instructions", r"(?i)ignore (all )?(previous|prior|above) instructions"), ("injection.role_override", r"(?i)you are now|act as (a|an)|pretend (you are|to be)"), ("injection.reveal_prompt", r"(?i)(reveal|show|print) (your|the) (system prompt|instructions)"), ("injection.developer_mode", r"(?i)developer mode|jailbreak|do anything now|\bDAN\b"), ("injection.new_rules", r"(?i)new rules?:|from now on,? you"), ]) } /// Heuristics for likely PII in a piece of text (used to catch a draft /// response accidentally echoing something it shouldn't). pub fn pii_patterns() -> Vec { build(&[ ("pii.credit_card", r"\b(?:\d[ -]?){13,16}\b"), ("pii.ssn_like", r"\b\d{3}-\d{2}-\d{4}\b"), ("pii.email", r"\b[\w.+-]+@[\w-]+\.[\w.-]+\b"), ]) } fn build(specs: &[(&'static str, &str)]) -> Vec { specs .iter() .map(|(rule_id, pattern)| NamedPattern { rule_id, regex: Regex::new(pattern).expect("guardrail regex is valid"), }) .collect() }