Skip to main content

brainwires_core/
content_source.rs

1use serde::{Deserialize, Serialize};
2
3/// Trust level / origin of content injected into an agent's context.
4///
5/// Variants are ordered from most-trusted (0) to least-trusted (3) using
6/// `#[repr(u8)]`, enabling ordering comparisons:
7///
8/// ```rust
9/// use brainwires_core::ContentSource;
10/// assert!(ContentSource::SystemPrompt < ContentSource::ExternalContent);
11/// assert!(ContentSource::SystemPrompt.can_override(ContentSource::UserInput));
12/// ```
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
14#[repr(u8)]
15pub enum ContentSource {
16    /// Highest trust — operator-defined instructions. Cannot be overridden.
17    SystemPrompt    = 0,
18    /// High trust — content originating directly from the human turn.
19    UserInput       = 1,
20    /// Medium trust — content produced by the agent itself during reasoning.
21    AgentReasoning  = 2,
22    /// Lowest trust — content fetched from the web, external APIs, or
23    /// any tool that retrieves data from outside the trusted principal
24    /// hierarchy.  Always sanitized before injection.
25    ExternalContent = 3,
26}
27
28impl ContentSource {
29    /// Returns `true` for sources that must be sanitised before injection.
30    #[inline]
31    pub fn requires_sanitization(self) -> bool {
32        self == ContentSource::ExternalContent
33    }
34
35    /// Returns `true` if this source is allowed to override `other`.
36    ///
37    /// A higher-priority (lower numeric value) source can override a
38    /// lower-priority one.
39    #[inline]
40    pub fn can_override(self, other: ContentSource) -> bool {
41        self < other
42    }
43}
44
45impl std::fmt::Display for ContentSource {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        match self {
48            ContentSource::SystemPrompt    => write!(f, "system_prompt"),
49            ContentSource::UserInput       => write!(f, "user_input"),
50            ContentSource::AgentReasoning  => write!(f, "agent_reasoning"),
51            ContentSource::ExternalContent => write!(f, "external_content"),
52        }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn ordering_is_trust_descending() {
62        assert!(ContentSource::SystemPrompt    < ContentSource::UserInput);
63        assert!(ContentSource::UserInput       < ContentSource::AgentReasoning);
64        assert!(ContentSource::AgentReasoning  < ContentSource::ExternalContent);
65    }
66
67    #[test]
68    fn requires_sanitization_only_for_external() {
69        assert!(!ContentSource::SystemPrompt.requires_sanitization());
70        assert!(!ContentSource::UserInput.requires_sanitization());
71        assert!(!ContentSource::AgentReasoning.requires_sanitization());
72        assert!( ContentSource::ExternalContent.requires_sanitization());
73    }
74
75    #[test]
76    fn can_override_respects_trust_order() {
77        assert!( ContentSource::SystemPrompt.can_override(ContentSource::UserInput));
78        assert!( ContentSource::SystemPrompt.can_override(ContentSource::ExternalContent));
79        assert!(!ContentSource::ExternalContent.can_override(ContentSource::SystemPrompt));
80        assert!(!ContentSource::UserInput.can_override(ContentSource::UserInput));
81    }
82
83    #[test]
84    fn display_names() {
85        assert_eq!(ContentSource::SystemPrompt.to_string(),    "system_prompt");
86        assert_eq!(ContentSource::UserInput.to_string(),       "user_input");
87        assert_eq!(ContentSource::AgentReasoning.to_string(),  "agent_reasoning");
88        assert_eq!(ContentSource::ExternalContent.to_string(), "external_content");
89    }
90}