Skip to main content

ADR-024-v4: Security Hardening Architecture - Part 2 (Technical)

Document Specification Block​

Document: ADR-024-v4-security-hardening-architecture-part2-technical
Version: 1.0.1
Purpose: Complete technical implementation blueprint for CODITECT security hardening
Audience: Implementation teams, security engineers, AI agents
Date Created: 2025-09-01
Date Modified: 2025-09-01
Status: DRAFT

Table of Contents​

↑ Back to Top

Implementation Constraints​

MUST Requirements​

  • Real-time threat detection with <5 second response time
  • FoundationDB storage for tamper-proof audit logs
  • Zero-trust verification for every request
  • Multi-tenant isolation at all security layers
  • eBPF monitoring for zero-overhead runtime security
  • Automated incident response with human approval gates
  • 100% security event logging with structured JSON

MUST NOT Requirements​

  • Store secrets in code or configuration files
  • Allow cross-tenant data access under any condition
  • Disable security features for performance
  • Log sensitive data (passwords, tokens, PII)
  • Trust client-provided security assertions

System Architecture​

// src/security/mod.rs
use actix_web::{web, HttpResponse, Result};
use serde::{Deserialize, Serialize};
use std::sync::Arc;

#[derive(Clone)]
pub struct SecurityEngine {
threat_detector: Arc<ThreatDetector>,
vulnerability_scanner: Arc<VulnerabilityScanner>,
runtime_monitor: Arc<RuntimeMonitor>,
incident_responder: Arc<IncidentResponder>,
security_logger: Arc<SecurityLogger>,
db: Arc<FoundationDBClient>,
}

impl SecurityEngine {
pub async fn new(db: Arc<FoundationDBClient>) -> Result<Self> {
Ok(Self {
threat_detector: Arc::new(ThreatDetector::new(db.clone())),
vulnerability_scanner: Arc::new(VulnerabilityScanner::new()),
runtime_monitor: Arc::new(RuntimeMonitor::new()),
incident_responder: Arc::new(IncidentResponder::new(db.clone())),
security_logger: Arc::new(SecurityLogger::new(db.clone())),
db,
})
}

pub async fn process_request(&self, req: SecurityRequest) -> Result<SecurityResponse> {
// 1. Pre-request validation
self.validate_request(&req).await?;

// 2. Threat detection
if let Some(threat) = self.threat_detector.analyze(&req).await? {
self.handle_threat(threat).await?;
return Ok(SecurityResponse::Blocked(threat.reason));
}

// 3. Runtime monitoring
let monitor_handle = self.runtime_monitor.track(&req).await?;

// 4. Process request (would be actual business logic)
let result = self.process_business_logic(&req).await?;

// 5. Post-request validation
self.validate_response(&result).await?;

// 6. Log security event
self.security_logger.log_request(&req, &result).await?;

Ok(result)
}
}

↑ Back to Top

Core Components​

1. Threat Detection Engine​

// src/security/threat_detector.rs
pub struct ThreatDetector {
ml_model: Arc<ThreatMLModel>,
rule_engine: Arc<RuleEngine>,
reputation_checker: Arc<ReputationChecker>,
behavior_analyzer: Arc<BehaviorAnalyzer>,
db: Arc<FoundationDBClient>,
}

impl ThreatDetector {
pub async fn analyze(&self, req: &SecurityRequest) -> Result<Option<Threat>> {
// Parallel threat analysis
let (ml_score, rule_match, reputation, behavior_anomaly) = tokio::join!(
self.ml_model.score(req),
self.rule_engine.check(req),
self.reputation_checker.check(&req.ip_address),
self.behavior_analyzer.is_anomalous(&req.user_id, req)
);

// Combine signals into threat assessment
let threat_score = self.calculate_threat_score(
ml_score?,
rule_match?,
reputation?,
behavior_anomaly?
);

if threat_score > THREAT_THRESHOLD {
Ok(Some(Threat {
id: Uuid::new_v4(),
severity: self.classify_severity(threat_score),
type_: self.identify_threat_type(req),
confidence: threat_score,
reason: self.build_threat_reason(req),
recommended_action: self.recommend_action(threat_score),
}))
} else {
Ok(None)
}
}
}

// ML-based threat detection
pub struct ThreatMLModel {
model: onnx::Model,
feature_extractor: FeatureExtractor,
}

impl ThreatMLModel {
pub async fn score(&self, req: &SecurityRequest) -> Result<f32> {
let features = self.feature_extractor.extract(req)?;
let input = ndarray::Array2::from_shape_vec((1, features.len()), features)?;
let output = self.model.run(vec![input])?;
Ok(output[0][[0, 0]])
}
}

↑ Back to Top

2. Vulnerability Scanner​

// src/security/vulnerability_scanner.rs
pub struct VulnerabilityScanner {
image_scanner: Arc<ContainerImageScanner>,
dependency_scanner: Arc<DependencyScanner>,
config_scanner: Arc<ConfigurationScanner>,
code_scanner: Arc<CodeScanner>,
}

impl VulnerabilityScanner {
pub async fn scan_deployment(&self, deployment: &Deployment) -> Result<VulnerabilityReport> {
let mut report = VulnerabilityReport::new();

// Scan container image
let image_vulns = self.image_scanner
.scan(&deployment.container_image)
.await?;
report.add_vulnerabilities(image_vulns);

// Scan dependencies
let dep_vulns = self.dependency_scanner
.scan(&deployment.dependencies)
.await?;
report.add_vulnerabilities(dep_vulns);

// Scan configuration
let config_vulns = self.config_scanner
.scan(&deployment.config)
.await?;
report.add_vulnerabilities(config_vulns);

// Prioritize by CVSS score and exploitability
report.prioritize();

Ok(report)
}
}

#[derive(Serialize, Deserialize)]
pub struct Vulnerability {
pub id: String, // CVE-YYYY-NNNNN
pub severity: Severity,
pub cvss_score: f32,
pub component: String,
pub version: String,
pub fixed_version: Option<String>,
pub exploit_available: bool,
pub patch_available: bool,
}

↑ Back to Top

3. Runtime Security Monitor​

// src/security/runtime_monitor.rs
use redbpf::{Program, Module};

pub struct RuntimeMonitor {
ebpf_module: Module,
anomaly_detector: Arc<AnomalyDetector>,
policy_enforcer: Arc<PolicyEnforcer>,
}

impl RuntimeMonitor {
pub fn new() -> Result<Self> {
// Load eBPF programs for system call monitoring
let mut module = Module::parse(include_bytes!("../bpf/monitor.o"))?;

// Attach to system calls
for program in module.programs.iter_mut() {
program.attach()?;
}

Ok(Self {
ebpf_module: module,
anomaly_detector: Arc::new(AnomalyDetector::new()),
policy_enforcer: Arc::new(PolicyEnforcer::new()),
})
}

pub async fn track(&self, req: &SecurityRequest) -> Result<MonitorHandle> {
let handle = MonitorHandle::new();

// Start monitoring container
let container_id = req.container_id.clone();
tokio::spawn(async move {
self.monitor_container(container_id).await
});

Ok(handle)
}

async fn monitor_container(&self, container_id: String) -> Result<()> {
// Real-time monitoring via eBPF
let events = self.ebpf_module.events();

while let Some(event) = events.next().await {
match event {
SystemCall { pid, syscall, args } => {
if self.is_suspicious_syscall(&syscall, &args) {
self.handle_suspicious_activity(pid, syscall, args).await?;
}
}
NetworkConnection { src, dst, protocol } => {
if !self.policy_enforcer.is_allowed(&src, &dst, &protocol) {
self.block_connection(src, dst).await?;
}
}
FileAccess { pid, path, mode } => {
if self.is_sensitive_path(&path) {
self.audit_file_access(pid, path, mode).await?;
}
}
}
}

Ok(())
}
}

↑ Back to Top

4. Incident Response Platform​

// src/security/incident_responder.rs
pub struct IncidentResponder {
playbook_engine: Arc<PlaybookEngine>,
forensics_collector: Arc<ForensicsCollector>,
containment_engine: Arc<ContainmentEngine>,
notification_service: Arc<NotificationService>,
db: Arc<FoundationDBClient>,
}

impl IncidentResponder {
pub async fn handle_incident(&self, threat: Threat) -> Result<IncidentResponse> {
// 1. Create incident record
let incident = Incident::from_threat(threat);
self.save_incident(&incident).await?;

// 2. Execute playbook based on threat type
let playbook = self.playbook_engine.select(&incident)?;

// 3. Automated containment (with approval gates)
if playbook.requires_immediate_action() {
self.containment_engine.isolate(&incident).await?;
}

// 4. Collect forensic evidence
let evidence = self.forensics_collector
.collect(&incident)
.await?;

// 5. Notify security team
self.notification_service
.alert_security_team(&incident)
.await?;

// 6. Execute remediation steps
let response = self.execute_playbook(playbook, &incident).await?;

Ok(response)
}

async fn execute_playbook(&self, playbook: Playbook, incident: &Incident) -> Result<IncidentResponse> {
let mut response = IncidentResponse::new();

for step in playbook.steps {
match step.action {
Action::DisableUser(user_id) => {
self.disable_user(&user_id).await?;
response.add_action("User disabled", user_id);
}
Action::IsolateContainer(container_id) => {
self.isolate_container(&container_id).await?;
response.add_action("Container isolated", container_id);
}
Action::BlockIP(ip) => {
self.block_ip(&ip).await?;
response.add_action("IP blocked", ip);
}
Action::RollbackDeployment(deployment_id) => {
self.rollback_deployment(&deployment_id).await?;
response.add_action("Deployment rolled back", deployment_id);
}
Action::RequireHumanApproval => {
self.await_human_approval(&incident).await?;
}
}
}

Ok(response)
}
}

↑ Back to Top

Database Schema​

# Security Events
/{tenant_id}/security_events/{timestamp}_{event_id}:
event_type: enum
severity: enum
user_id: string
ip_address: string
threat_score: f32
action_taken: string
details: json

# Vulnerabilities
/{tenant_id}/vulnerabilities/{component}/{cve_id}:
severity: enum
cvss_score: f32
discovered_at: timestamp
patched_at: timestamp?
exploit_available: bool

# Incidents
/{tenant_id}/incidents/{incident_id}:
threat_id: string
severity: enum
status: enum
created_at: timestamp
resolved_at: timestamp?
responder: string
playbook_used: string
evidence: string[]

# Security Policies
/{tenant_id}/security_policies/{policy_id}:
name: string
type: enum
rules: json
enabled: bool
created_by: string
updated_at: timestamp

↑ Back to Top

API Endpoints​

# Threat Detection
POST /api/v1/security/threats/analyze:
body: { request_context: RequestContext }
response: { threat_detected: bool, threat?: Threat, recommendation?: string }

# Vulnerability Management
GET /api/v1/security/vulnerabilities:
response: { vulnerabilities: Vulnerability[], summary: VulnSummary }

POST /api/v1/security/vulnerabilities/scan:
body: { target: ScanTarget }
response: { scan_id: string, status: string }

# Incident Response
POST /api/v1/security/incidents:
body: { threat: Threat, context: IncidentContext }
response: { incident_id: string, response: IncidentResponse }

GET /api/v1/security/incidents/{id}:
response: { incident: Incident, timeline: Event[], evidence: Evidence[] }

# Security Policies
PUT /api/v1/security/policies/{id}:
body: { policy: SecurityPolicy }
response: { updated: bool, validation: PolicyValidation }

↑ Back to Top

Security Configurations​

# k8s/security-policies.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
spec:
mtls:
mode: STRICT

---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: coditect-authz
spec:
selector:
matchLabels:
app: coditect
rules:
- from:
- source:
principals: ["cluster.local/ns/coditect/sa/api-server"]
to:
- operation:
methods: ["GET", "POST", "PUT", "DELETE"]

---
apiVersion: v1
kind: NetworkPolicy
metadata:
name: coditect-network-policy
spec:
podSelector:
matchLabels:
app: coditect
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: coditect
ports:
- protocol: TCP
port: 8080

↑ Back to Top

Error Handling​

#[derive(Debug, thiserror::Error)]
pub enum SecurityError {
#[error("Authentication failed")]
AuthenticationFailed,

#[error("Authorization denied")]
AuthorizationDenied,

#[error("Threat detected: {0}")]
ThreatDetected(String),

#[error("Security policy violation")]
PolicyViolation,

#[error("Incident response failed")]
IncidentResponseFailed,
}

impl SecurityError {
pub fn user_message(&self) -> String {
match self {
Self::AuthenticationFailed => "Invalid credentials".into(),
Self::AuthorizationDenied => "Access denied".into(),
Self::ThreatDetected(_) => "Request blocked for security reasons".into(),
Self::PolicyViolation => "Action violates security policy".into(),
Self::IncidentResponseFailed => "Security incident being handled".into(),
}
}

pub fn should_alert_security(&self) -> bool {
matches!(self,
Self::ThreatDetected(_) |
Self::PolicyViolation |
Self::IncidentResponseFailed
)
}
}

↑ Back to Top

Logging Implementation​

// src/security/logging.rs
use coditect::logging::{Logger, LogLevel, LogEntry};

pub struct SecurityLogger {
logger: Arc<Logger>,
db: Arc<FoundationDBClient>,
}

impl SecurityLogger {
pub async fn log_security_event(&self, event: SecurityEvent) {
let entry = LogEntry {
timestamp: Utc::now(),
level: self.severity_to_level(event.severity),
component: "security",
action: event.event_type.to_string(),
tenant_id: Some(event.tenant_id),
user_id: event.user_id,
details: json!({
"ip_address": event.ip_address,
"threat_score": event.threat_score,
"action_taken": event.action_taken,
"metadata": event.metadata,
}),
};

// Log to both logging system and permanent security audit
self.logger.log(entry.clone()).await;
self.store_security_audit(entry).await;
}

async fn store_security_audit(&self, entry: LogEntry) {
let key = format!(
"{}/security_audit/{}_{}",
entry.tenant_id.unwrap_or_default(),
entry.timestamp.timestamp_nanos(),
Uuid::new_v4()
);

self.db.transact(|txn| {
txn.set(&key, &serialize(&entry)?);
Ok(())
}).await.unwrap_or_else(|e| {
error!("Failed to store security audit: {}", e);
});
}
}

↑ Back to Top

Testing Requirements​

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
async fn test_threat_detection() {
let engine = SecurityEngine::new_test().await;

// Test SQL injection detection
let malicious_req = SecurityRequest {
path: "/api/users",
params: vec![("id", "1'; DROP TABLE users; --")],
..Default::default()
};

let result = engine.process_request(malicious_req).await;
assert!(matches!(result, Err(SecurityError::ThreatDetected(_))));
}

#[tokio::test]
async fn test_incident_response() {
let responder = IncidentResponder::new_test().await;

let threat = Threat {
severity: Severity::Critical,
type_: ThreatType::DataExfiltration,
..Default::default()
};

let response = responder.handle_incident(threat).await.unwrap();
assert!(response.actions.contains(&"User disabled"));
assert!(response.actions.contains(&"Container isolated"));
}

#[tokio::test]
async fn test_vulnerability_scanning() {
let scanner = VulnerabilityScanner::new();

let deployment = Deployment {
container_image: "nginx:1.14.0", // Known vulnerable version
..Default::default()
};

let report = scanner.scan_deployment(&deployment).await.unwrap();
assert!(!report.vulnerabilities.is_empty());
assert!(report.has_critical_vulnerabilities());
}
}

↑ Back to Top

Deployment Configuration​

# k8s/security-engine-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: security-engine
spec:
replicas: 3
template:
spec:
serviceAccountName: security-engine
securityContext:
runAsNonRoot: true
fsGroup: 65534
containers:
- name: security-engine
image: coditect/security-engine:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 65534
capabilities:
drop:
- ALL
add:
- NET_ADMIN # For eBPF
env:
- name: FDB_CLUSTER_FILE
value: /etc/fdb/fdb.cluster
- name: RUST_LOG
value: security=debug,info
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
volumeMounts:
- name: ebpf-maps
mountPath: /sys/fs/bpf
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
volumes:
- name: ebpf-maps
hostPath:
path: /sys/fs/bpf
type: Directory

↑ Back to Top

Performance Benchmarks​

  • Threat detection latency: P99 < 50ms
  • Vulnerability scan time: <30s for container image
  • Incident response time: <5s for automated actions
  • Security event logging: 100K events/second
  • Memory usage: <512MB per instance
  • CPU overhead: <5% for runtime monitoring

↑ Back to Top

File Structure​

src/security/
├── mod.rs # Main security engine
├── threat_detector.rs # Threat detection logic
├── vulnerability_scanner.rs # Vulnerability scanning
├── runtime_monitor.rs # eBPF runtime monitoring
├── incident_responder.rs # Incident response
├── logging.rs # Security logging
├── policies/
│ ├── mod.rs # Policy engine
│ └── rules.rs # Security rules
├── ml/
│ ├── mod.rs # ML models
│ └── features.rs # Feature extraction
└── bpf/
└── monitor.c # eBPF programs

This implementation provides comprehensive security hardening with real-time threat detection, automated incident response, and continuous monitoring while maintaining CODITECT's performance and multi-tenant isolation requirements.

↑ Back to Top