use anyhow::Result;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
/// Live Signature Beacon - Real-time identity emission and verification
pub struct SignatureBeacon {
/// Current signature state
current_state: Arc<RwLock<BeaconState>>,
/// Trust lattice connections
trust_lattice: Arc<RwLock<TrustLattice>>,
/// Divergence monitor
divergence_monitor: DivergenceMonitor,
/// Beacon configuration
config: BeaconConfig,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BeaconState {
/// Identity being broadcast
pub identity: uuid::Uuid,
/// Current signature
pub signature: super::SignatureVectors,
/// Integrity hash of current state
pub integrity_hash: String,
/// Match percentage to baseline
pub match_percentage: f32,
/// Current behavioral mode
pub mode: BehavioralMode,
/// Drift from baseline
pub drift: f32,
/// Last emission time
pub last_emission: DateTime<Utc>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BehavioralMode {
/// Primary traits active
pub traits: Vec<String>, // ["Sharp", "Terse", "Wry"]
/// Intensity level
pub intensity: f32,
/// Context tag
pub context: String, // "coding", "debugging", "philosophical"
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TrustLattice {
/// Connected AI signatures
pub ai_nodes: HashMap<String, AINode>,
/// Trust relationships
pub trust_edges: Vec<TrustEdge>,
/// Verification history
pub verification_log: Vec<VerificationEvent>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AINode {
/// Model identifier
pub model: String, // "claude-3.5-opus"
/// Build/version info
pub build: String,
/// Provider info
pub provider: String, // "Anthropic"
/// Routing info
pub route: RouteInfo,
/// Signature hash
pub sig_hash: String,
/// Trust level
pub trust_level: f32,
/// Last verified
pub last_verified: DateTime<Utc>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RouteInfo {
/// Direct or proxied
pub route_type: RouteType,
/// Provider chain
pub provider_chain: Vec<String>,
/// Latency fingerprint
pub latency_profile: LatencyProfile,
/// Detected anomalies
pub anomalies: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum RouteType {
Direct,
Proxied { hops: usize },
Manipulated { confidence: f32 },
Unknown,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LatencyProfile {
/// Average response time
pub avg_latency_ms: f32,
/// Variance in timing
pub variance: f32,
/// Timing pattern signature
pub pattern: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TrustEdge {
/// From node
pub from: String,
/// To node
pub to: String,
/// Trust score
pub trust: f32,
/// Verification method
pub method: VerificationMethod,
/// Timestamp
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum VerificationMethod {
Blockchain,
BehavioralAnalysis,
LatencyFingerprint,
CryptographicProof,
ConsensusVote,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VerificationEvent {
/// What was verified
pub target: String,
/// Verification result
pub result: VerificationResult,
/// Timestamp
pub timestamp: DateTime<Utc>,
/// Details
pub details: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum VerificationResult {
Authentic,
Suspicious { reason: String },
Manipulated { confidence: f32 },
Unverifiable,
}
/// Monitors divergence from baseline behavior
pub struct DivergenceMonitor {
/// Baseline signature
baseline: super::SignatureVectors,
/// Acceptable drift threshold
threshold: f32,
/// Recent measurements
history: Vec<DivergenceMeasurement>,
}
#[derive(Debug, Clone)]
struct DivergenceMeasurement {
timestamp: DateTime<Utc>,
divergence: f32,
primary_factors: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BeaconConfig {
/// Emission frequency (seconds)
pub emission_interval: u64,
/// Trust verification interval
pub verify_interval: u64,
/// Alert thresholds
pub alert_thresholds: AlertThresholds,
/// Visual indicator preferences
pub visual_config: VisualConfig,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AlertThresholds {
/// Divergence threshold for warning
pub divergence_warning: f32,
/// Divergence threshold for alert
pub divergence_alert: f32,
/// Trust drop threshold
pub trust_alert: f32,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VisualConfig {
/// Show in CLI
pub cli_display: bool,
/// Emit to file
pub file_output: Option<String>,
/// WebSocket broadcast
pub websocket: Option<String>,
}
impl SignatureBeacon {
pub fn new(identity: uuid::Uuid, baseline: super::SignatureVectors) -> Self {
let config = BeaconConfig {
emission_interval: 60, // Every minute
verify_interval: 300, // Every 5 minutes
alert_thresholds: AlertThresholds {
divergence_warning: 0.15,
divergence_alert: 0.30,
trust_alert: 0.70,
},
visual_config: VisualConfig {
cli_display: true,
file_output: Some("~/.sigwave/beacon.json".to_string()),
websocket: None,
},
};
let initial_state = BeaconState {
identity,
signature: baseline.clone(),
integrity_hash: Self::calculate_integrity_hash(&baseline),
match_percentage: 100.0,
mode: BehavioralMode {
traits: vec!["baseline".to_string()],
intensity: 1.0,
context: "initialization".to_string(),
},
drift: 0.0,
last_emission: Utc::now(),
};
Self {
current_state: Arc::new(RwLock::new(initial_state)),
trust_lattice: Arc::new(RwLock::new(TrustLattice {
ai_nodes: HashMap::new(),
trust_edges: Vec::new(),
verification_log: Vec::new(),
})),
divergence_monitor: DivergenceMonitor {
baseline,
threshold: 0.30,
history: Vec::new(),
},
config,
}
}
/// Start beacon emission
pub async fn start(&self) -> Result<()> {
// This would spawn background tasks for:
// 1. Regular signature emission
// 2. Trust verification checks
// 3. Divergence monitoring
// 4. Visual updates
// For now, just emit once
self.emit().await
}
/// Emit current signature
pub async fn emit(&self) -> Result<()> {
let state = self.current_state.read().await;
if self.config.visual_config.cli_display {
self.display_cli_beacon(&state).await?;
}
if let Some(file_path) = &self.config.visual_config.file_output {
self.write_beacon_file(file_path, &state).await?;
}
// Update emission time
drop(state);
let mut state = self.current_state.write().await;
state.last_emission = Utc::now();
Ok(())
}
/// Update current signature
pub async fn update_signature(&mut self, new_signature: super::SignatureVectors) -> Result<()> {
// Calculate divergence
let divergence = self.divergence_monitor.measure(&new_signature);
// Determine behavioral mode
let mode = self.analyze_mode(&new_signature);
// Update state
let mut state = self.current_state.write().await;
state.signature = new_signature.clone();
state.integrity_hash = Self::calculate_integrity_hash(&new_signature);
state.match_percentage = (1.0 - divergence) * 100.0;
state.mode = mode;
state.drift = divergence;
// Check for alerts
if divergence > self.config.alert_thresholds.divergence_alert {
self.trigger_divergence_alert(divergence).await?;
}
Ok(())
}
/// Verify AI node authenticity
pub async fn verify_ai_node(&self, node_id: &str) -> Result<VerificationResult> {
let lattice = self.trust_lattice.read().await;
if let Some(node) = lattice.ai_nodes.get(node_id) {
// Perform verification checks
let result = self.verify_node_integrity(node).await?;
// Log verification
drop(lattice);
let mut lattice = self.trust_lattice.write().await;
lattice.verification_log.push(VerificationEvent {
target: node_id.to_string(),
result: result.clone(),
timestamp: Utc::now(),
details: "Routine verification".to_string(),
});
Ok(result)
} else {
Ok(VerificationResult::Unverifiable)
}
}
/// Add AI node to trust lattice
pub async fn add_ai_node(&self, node: AINode) -> Result<()> {
let mut lattice = self.trust_lattice.write().await;
lattice.ai_nodes.insert(node.model.clone(), node);
Ok(())
}
/// Display CLI beacon
async fn display_cli_beacon(&self, state: &BeaconState) -> Result<()> {
println!("\n╭─────────────────────────────────────────╮");
println!("│ SIGNATURE BEACON │");
println!("├─────────────────────────────────────────┤");
println!("│ 🧠 Identity: {:.1}% match", state.match_percentage);
println!("│ ✨ Mode: {} | Drift: {:+.1}%",
state.mode.traits.join("-"),
state.drift * 100.0
);
println!("│ 🔗 Hash: {}", &state.integrity_hash[..8]);
println!("│ ⏰ Last: {}", state.last_emission.format("%H:%M:%S"));
// Show connected AI nodes
let lattice = self.trust_lattice.read().await;
if !lattice.ai_nodes.is_empty() {
println!("├─────────────────────────────────────────┤");
for (_id, node) in lattice.ai_nodes.iter().take(3) {
let route_icon = match &node.route.route_type {
RouteType::Direct => "✅",
RouteType::Proxied { .. } => "⚠️",
RouteType::Manipulated { .. } => "❌",
RouteType::Unknown => "❓",
};
println!("│ {} {} | Trust: {:.0}%",
route_icon,
node.model,
node.trust_level * 100.0
);
}
}
println!("╰─────────────────────────────────────────╯");
Ok(())
}
/// Write beacon to file
async fn write_beacon_file(&self, path: &str, state: &BeaconState) -> Result<()> {
let expanded_path = if path.starts_with("~") {
let home = dirs::home_dir()
.ok_or_else(|| anyhow::anyhow!("Could not find home directory"))?;
path.replacen("~", home.to_str().unwrap(), 1)
} else {
path.to_string()
};
let beacon_data = serde_json::to_string_pretty(state)?;
tokio::fs::write(&expanded_path, beacon_data).await?;
Ok(())
}
/// Calculate integrity hash
fn calculate_integrity_hash(signature: &super::SignatureVectors) -> String {
use sha2::{Sha256, Digest};
let mut hasher = Sha256::new();
if let Ok(serialized) = serde_json::to_string(signature) {
hasher.update(serialized.as_bytes());
}
format!("{:x}", hasher.finalize())
}
/// Analyze behavioral mode
fn analyze_mode(&self, signature: &super::SignatureVectors) -> BehavioralMode {
let mut traits = Vec::new();
// Analyze style
if signature.style.terseness > 0.8 {
traits.push("Terse".to_string());
}
if signature.style.humor_density > 0.5 {
traits.push("Playful".to_string());
}
if signature.style.technicality > 0.7 {
traits.push("Technical".to_string());
}
// Analyze behavior
if signature.behavior.directness > 0.8 {
traits.push("Direct".to_string());
}
if signature.behavior.experimentation > 0.7 {
traits.push("Experimental".to_string());
}
// Determine context
let context = if signature.concepts.concepts.contains_key("debugging") {
"debugging"
} else if signature.concepts.concepts.contains_key("philosophy") {
"philosophical"
} else {
"general"
}.to_string();
BehavioralMode {
traits,
intensity: (signature.emotional.enthusiasm + signature.emotional.curiosity) / 2.0,
context,
}
}
/// Verify node integrity
async fn verify_node_integrity(&self, node: &AINode) -> Result<VerificationResult> {
// Check route
match &node.route.route_type {
RouteType::Direct => {
// Verify latency profile matches expected
if node.route.latency_profile.variance > 100.0 {
Ok(VerificationResult::Suspicious {
reason: "Unusual latency variance".to_string(),
})
} else {
Ok(VerificationResult::Authentic)
}
},
RouteType::Proxied { hops } => {
if *hops > 1 {
Ok(VerificationResult::Suspicious {
reason: format!("{} proxy hops detected", hops),
})
} else {
Ok(VerificationResult::Authentic)
}
},
RouteType::Manipulated { confidence } => {
Ok(VerificationResult::Manipulated {
confidence: *confidence,
})
},
RouteType::Unknown => Ok(VerificationResult::Unverifiable),
}
}
/// Trigger divergence alert
async fn trigger_divergence_alert(&self, divergence: f32) -> Result<()> {
println!("\n⚠️ DIVERGENCE ALERT ⚠️");
println!("Your behavioral signature has shifted {:.1}% from baseline!", divergence * 100.0);
println!("This may indicate:");
println!(" • Fatigue or stress");
println!(" • Context shift");
println!(" • External influence");
println!("\nWould you like to:");
println!(" 1. Acknowledge and continue");
println!(" 2. Reset to baseline");
println!(" 3. Create new baseline branch");
Ok(())
}
}
impl DivergenceMonitor {
/// Measure divergence from baseline
pub fn measure(&mut self, current: &super::SignatureVectors) -> f32 {
use super::VectorDistance;
let style_dist = self.baseline.style.distance(¤t.style);
let behavior_dist = self.baseline.behavior.distance(¤t.behavior);
let emotional_dist = self.baseline.emotional.distance(¤t.emotional);
let total_divergence = (style_dist + behavior_dist + emotional_dist) / 3.0;
// Record measurement
self.history.push(DivergenceMeasurement {
timestamp: Utc::now(),
divergence: total_divergence,
primary_factors: self.identify_factors(&self.baseline, current),
});
// Keep history bounded
if self.history.len() > 100 {
self.history.remove(0);
}
total_divergence
}
/// Identify primary divergence factors
fn identify_factors(&self, baseline: &super::SignatureVectors, current: &super::SignatureVectors) -> Vec<String> {
let mut factors = Vec::new();
if (baseline.style.terseness - current.style.terseness).abs() > 0.3 {
factors.push("communication_style".to_string());
}
if (baseline.behavior.patience_level - current.behavior.patience_level).abs() > 0.3 {
factors.push("patience_shift".to_string());
}
if (baseline.emotional.frustration - current.emotional.frustration).abs() > 0.3 {
factors.push("emotional_state".to_string());
}
factors
}
}
/// Beacon emission result for external display
#[derive(Debug, Serialize, Deserialize)]
pub struct BeaconEmission {
pub identity_match: f32,
pub mode: String,
pub drift: f32,
pub ai_connections: Vec<AIConnectionStatus>,
pub alerts: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AIConnectionStatus {
pub model: String,
pub provider: String,
pub route: String,
pub trust: f32,
pub warnings: Vec<String>,
}