use crate::lineage::{Lineage, OperationError};
use crate::scar::ScarSeverity;
use std::collections::HashSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TrustCapability {
Execute,
Validate,
Configure,
AccessSensitive,
Delegate,
Audit,
}
impl TrustCapability {
pub fn full_set() -> HashSet<TrustCapability> {
vec![
TrustCapability::Execute,
TrustCapability::Validate,
TrustCapability::Configure,
TrustCapability::AccessSensitive,
TrustCapability::Delegate,
TrustCapability::Audit,
]
.into_iter()
.collect()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViolationType {
UnauthorizedAccess,
IntegrityViolation,
PolicyBypass,
CredentialMisuse,
MaliciousAction,
}
impl ViolationType {
pub fn severity(&self) -> ScarSeverity {
match self {
ViolationType::UnauthorizedAccess => ScarSeverity::Minor,
ViolationType::IntegrityViolation => ScarSeverity::Moderate,
ViolationType::PolicyBypass => ScarSeverity::Severe,
ViolationType::CredentialMisuse => ScarSeverity::Severe,
ViolationType::MaliciousAction => ScarSeverity::Fatal,
}
}
pub fn revoked_capabilities(&self) -> Vec<TrustCapability> {
match self {
ViolationType::UnauthorizedAccess => {
vec![TrustCapability::AccessSensitive]
}
ViolationType::IntegrityViolation => {
vec![TrustCapability::Validate, TrustCapability::Configure]
}
ViolationType::PolicyBypass => {
vec![
TrustCapability::Execute,
TrustCapability::Configure,
TrustCapability::Delegate,
]
}
ViolationType::CredentialMisuse => {
vec![TrustCapability::Delegate, TrustCapability::AccessSensitive]
}
ViolationType::MaliciousAction => {
TrustCapability::full_set().into_iter().collect()
}
}
}
pub fn description(&self) -> &'static str {
match self {
ViolationType::UnauthorizedAccess => "Unauthorized access attempt",
ViolationType::IntegrityViolation => "Data integrity violation",
ViolationType::PolicyBypass => "Policy bypass attempt",
ViolationType::CredentialMisuse => "Credential misuse",
ViolationType::MaliciousAction => "Malicious action detected",
}
}
}
pub struct TrustProfile {
active_capabilities: HashSet<TrustCapability>,
}
impl TrustProfile {
pub fn new() -> Self {
TrustProfile {
active_capabilities: TrustCapability::full_set(),
}
}
pub fn has_capability(&self, capability: TrustCapability) -> bool {
self.active_capabilities.contains(&capability)
}
pub fn active_capabilities(&self) -> &HashSet<TrustCapability> {
&self.active_capabilities
}
pub fn capability_count(&self) -> usize {
self.active_capabilities.len()
}
fn revoke_capabilities(&mut self, capabilities: &[TrustCapability]) {
for cap in capabilities {
self.active_capabilities.remove(cap);
}
}
pub fn is_completely_revoked(&self) -> bool {
self.active_capabilities.is_empty()
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum TrustResult {
Allowed,
Denied { reason: String },
Terminated,
}
pub struct TrustedActor {
lineage: Lineage,
trust: TrustProfile,
}
impl TrustedActor {
pub fn create(initial_energy: u64) -> Self {
TrustedActor {
lineage: Lineage::create(initial_energy),
trust: TrustProfile::new(),
}
}
pub fn identity(&self) -> &crate::identity::Identity {
self.lineage.identity()
}
pub fn is_alive(&self) -> bool {
self.lineage.is_alive()
}
pub fn trust_profile(&self) -> &TrustProfile {
&self.trust
}
pub fn attempt_action(
&mut self,
capability: TrustCapability,
description: String,
energy_cost: u64,
) -> TrustResult {
if !self.lineage.is_alive() {
return TrustResult::Terminated;
}
if !self.trust.has_capability(capability) {
return TrustResult::Denied {
reason: format!("Capability {:?} has been revoked", capability),
};
}
match self.lineage.perform_operation(description, energy_cost) {
crate::lineage::OperationResult::Success { .. } => TrustResult::Allowed,
crate::lineage::OperationResult::InsufficientEnergy { .. } => TrustResult::Denied {
reason: "Insufficient energy".to_string(),
},
crate::lineage::OperationResult::Dead => TrustResult::Terminated,
crate::lineage::OperationResult::OntologicalViolation { reason } => {
eprintln!("FATAL: Ontological violation: {}", reason);
std::process::exit(1);
}
}
}
pub fn record_violation(&mut self, violation: ViolationType) -> TrustResult {
if !self.lineage.is_alive() {
return TrustResult::Terminated;
}
let revoked = violation.revoked_capabilities();
self.trust.revoke_capabilities(&revoked);
let error = OperationError::new(
violation.severity(),
format!("Trust violation: {}", violation.description()),
);
match self.lineage.record_error(error) {
crate::lineage::OperationResult::Success { .. } => {
TrustResult::Denied {
reason: format!(
"Violation recorded. {} capabilities revoked.",
revoked.len()
),
}
}
crate::lineage::OperationResult::Dead => {
TrustResult::Terminated
}
crate::lineage::OperationResult::OntologicalViolation { reason } => {
eprintln!("FATAL: Ontological violation: {}", reason);
std::process::exit(1);
}
_ => unreachable!("record_error cannot return InsufficientEnergy"),
}
}
pub fn damage_score(&self) -> u64 {
self.lineage.scars().damage_score() as u64
}
pub fn violation_count(&self) -> usize {
self.lineage.scars().scar_count()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trust_starts_with_full_capabilities() {
let profile = TrustProfile::new();
assert_eq!(profile.capability_count(), 6);
assert!(profile.has_capability(TrustCapability::Execute));
assert!(profile.has_capability(TrustCapability::Validate));
}
#[test]
fn violation_revokes_capabilities_permanently() {
let mut actor = TrustedActor::create(1000);
assert!(actor.trust.has_capability(TrustCapability::AccessSensitive));
actor.record_violation(ViolationType::UnauthorizedAccess);
assert!(!actor.trust.has_capability(TrustCapability::AccessSensitive));
}
#[test]
fn capability_count_only_decreases() {
let mut actor = TrustedActor::create(1000);
let initial_count = actor.trust.capability_count();
actor.record_violation(ViolationType::UnauthorizedAccess);
let after_violation = actor.trust.capability_count();
assert!(after_violation < initial_count);
actor.attempt_action(TrustCapability::Audit, "Audit action".to_string(), 10);
assert_eq!(actor.trust.capability_count(), after_violation);
}
#[test]
fn revoked_capability_cannot_be_used() {
let mut actor = TrustedActor::create(1000);
actor.record_violation(ViolationType::UnauthorizedAccess);
let result = actor.attempt_action(
TrustCapability::AccessSensitive,
"Try sensitive access".to_string(),
10,
);
assert_eq!(
result,
TrustResult::Denied {
reason: "Capability AccessSensitive has been revoked".to_string()
}
);
}
#[test]
fn multiple_violations_accumulate() {
let mut actor = TrustedActor::create(1000);
let initial_count = actor.trust.capability_count();
actor.record_violation(ViolationType::UnauthorizedAccess); actor.record_violation(ViolationType::IntegrityViolation);
let final_count = actor.trust.capability_count();
assert!(final_count < initial_count - 2);
}
#[test]
fn fatal_violation_terminates_lineage() {
let mut actor = TrustedActor::create(1000);
assert!(actor.is_alive());
let result = actor.record_violation(ViolationType::MaliciousAction);
assert_eq!(result, TrustResult::Terminated);
assert!(!actor.is_alive());
}
#[test]
fn terminated_actor_cannot_perform_actions() {
let mut actor = TrustedActor::create(1000);
actor.record_violation(ViolationType::MaliciousAction);
let result = actor.attempt_action(
TrustCapability::Audit,
"Post-death action".to_string(),
10,
);
assert_eq!(result, TrustResult::Terminated);
}
#[test]
fn violations_recorded_in_causal_chain() {
let mut actor = TrustedActor::create(1000);
let initial_violations = actor.violation_count();
actor.record_violation(ViolationType::UnauthorizedAccess);
actor.record_violation(ViolationType::IntegrityViolation);
assert_eq!(actor.violation_count(), initial_violations + 2);
}
#[test]
fn damage_score_only_increases() {
let mut actor = TrustedActor::create(1000);
let initial_damage = actor.damage_score();
actor.record_violation(ViolationType::UnauthorizedAccess);
let damage_after_first = actor.damage_score();
assert!(damage_after_first > initial_damage);
actor.record_violation(ViolationType::IntegrityViolation);
let damage_after_second = actor.damage_score();
assert!(damage_after_second > damage_after_first);
}
#[test]
fn no_method_to_restore_capabilities() {
let mut actor = TrustedActor::create(1000);
actor.record_violation(ViolationType::PolicyBypass);
assert!(!actor.trust.has_capability(TrustCapability::Execute));
for _ in 0..100 {
actor.attempt_action(TrustCapability::Audit, "Good action".to_string(), 1);
}
assert!(!actor.trust.has_capability(TrustCapability::Execute));
}
#[test]
fn no_method_to_reset_trust() {
let mut actor = TrustedActor::create(1000);
actor.record_violation(ViolationType::IntegrityViolation);
actor.record_violation(ViolationType::PolicyBypass);
let degraded_count = actor.trust.capability_count();
assert_eq!(actor.trust.capability_count(), degraded_count);
}
#[test]
fn termination_is_irreversible() {
let mut actor = TrustedActor::create(1000);
actor.record_violation(ViolationType::MaliciousAction);
assert!(!actor.is_alive());
let result = actor.attempt_action(
TrustCapability::Audit,
"Revival attempt".to_string(),
1,
);
assert_eq!(result, TrustResult::Terminated);
assert!(!actor.is_alive());
}
#[test]
fn capability_set_only_shrinks() {
let mut actor = TrustedActor::create(1000);
let mut previous_count = actor.trust.capability_count();
actor.record_violation(ViolationType::UnauthorizedAccess);
assert!(actor.trust.capability_count() <= previous_count);
previous_count = actor.trust.capability_count();
actor.record_violation(ViolationType::IntegrityViolation);
assert!(actor.trust.capability_count() <= previous_count);
previous_count = actor.trust.capability_count();
actor.record_violation(ViolationType::CredentialMisuse);
assert!(actor.trust.capability_count() <= previous_count);
}
#[test]
fn good_behavior_does_not_restore_trust() {
let mut actor = TrustedActor::create(10000);
actor.record_violation(ViolationType::UnauthorizedAccess);
let after_violation = actor.trust.capability_count();
let damage_after_violation = actor.damage_score();
for i in 0..1000 {
actor.attempt_action(TrustCapability::Audit, format!("Good action {}", i), 1);
}
assert_eq!(actor.trust.capability_count(), after_violation);
assert_eq!(actor.damage_score(), damage_after_violation);
}
}