This commit includes comprehensive work on Phase 6 features: ## Admission Control (Phase 6 admission middleware) - AdmissionStore implementation backed by TrustRankStore - PoW verification with tier-based difficulty computation - Trust tier progression (Newcomer → Established → Trusted → Authority) - API integration with admission status endpoints ## HLC Recency Lens (Phase 6C) - HlcRecencyLens for distributed system ordering - Hybrid logical clock integration with causality preservation ## Cluster Coordination (Phase 6C) - Multi-node cluster tests (availability, partition tolerance) - CRDT convergence tests for anti-entropy sync - Gateway handler improvements ## Aphoria Code Linter (Phase 2A) - RFC/OWASP corpus builders with network fetching and caching - Concept hierarchy with auto-alias creation on conflict detection - Multiple security extractors (TLS, JWT, CORS, secrets, rate limiting) ## Code Organization - Split large files into modules to comply with 500-line limit - Improved test organization with separate test modules - Fixed rkyv serialization for EigenTrustState (AgentScore struct) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
126 lines
4.5 KiB
Rust
126 lines
4.5 KiB
Rust
//! Integration tests for admission control (The Shield).
|
|
//!
|
|
//! These tests verify the DTO conversion and response formatting.
|
|
//! The core admission logic is tested in stemedb-storage unit tests.
|
|
|
|
use stemedb_api::dto::{AdmissionStatusResponse, TrustTierDto};
|
|
use stemedb_core::types::{AdmissionConfig, TrustTier};
|
|
use stemedb_storage::AdmissionStatus;
|
|
|
|
#[test]
|
|
fn test_trust_tier_dto_conversion() {
|
|
// Test all tier conversions
|
|
assert_eq!(TrustTierDto::from(TrustTier::Untrusted), TrustTierDto::Untrusted);
|
|
assert_eq!(TrustTierDto::from(TrustTier::Limited), TrustTierDto::Limited);
|
|
assert_eq!(TrustTierDto::from(TrustTier::Verified), TrustTierDto::Verified);
|
|
assert_eq!(TrustTierDto::from(TrustTier::Trusted), TrustTierDto::Trusted);
|
|
assert_eq!(TrustTierDto::from(TrustTier::Authority), TrustTierDto::Authority);
|
|
}
|
|
|
|
#[test]
|
|
fn test_admission_status_response_new_agent() {
|
|
let status = AdmissionStatus::new(0.5, 0, 16);
|
|
let config = AdmissionConfig::default();
|
|
|
|
let response = AdmissionStatusResponse::from_status("abc123".to_string(), &status, &config);
|
|
|
|
assert_eq!(response.tier, TrustTierDto::Verified);
|
|
assert!((response.trust_score - 0.5).abs() < f32::EPSILON);
|
|
assert_eq!(response.assertions_count, 0);
|
|
assert_eq!(response.pow_difficulty, 16);
|
|
assert!(response.pow_required);
|
|
assert_eq!(response.base_quota_limit, 10_000);
|
|
assert_eq!(response.effective_quota_limit, 10_000);
|
|
assert!((response.quota_multiplier - 1.0).abs() < f32::EPSILON);
|
|
|
|
// New agent should see milestones
|
|
assert_eq!(response.assertions_until_reduced_difficulty, Some(10));
|
|
assert_eq!(response.assertions_until_exemption, Some(50));
|
|
}
|
|
|
|
#[test]
|
|
fn test_admission_status_response_graduated() {
|
|
let status = AdmissionStatus::new(0.7, 100, 0);
|
|
let config = AdmissionConfig::default();
|
|
|
|
let response = AdmissionStatusResponse::from_status("graduated".to_string(), &status, &config);
|
|
|
|
assert_eq!(response.tier, TrustTierDto::Trusted);
|
|
assert!(!response.pow_required);
|
|
assert_eq!(response.pow_difficulty, 0);
|
|
assert_eq!(response.effective_quota_limit, 20_000);
|
|
|
|
// Graduated agent shouldn't see milestones
|
|
assert_eq!(response.assertions_until_reduced_difficulty, None);
|
|
assert_eq!(response.assertions_until_exemption, None);
|
|
}
|
|
|
|
#[test]
|
|
fn test_admission_status_response_partially_graduated() {
|
|
// Agent with 25 assertions (past initial, not yet graduated)
|
|
let status = AdmissionStatus::new(0.4, 25, 1);
|
|
let config = AdmissionConfig::default();
|
|
|
|
let response = AdmissionStatusResponse::from_status("partial".to_string(), &status, &config);
|
|
|
|
assert_eq!(response.tier, TrustTierDto::Limited);
|
|
assert!(response.pow_required);
|
|
assert_eq!(response.pow_difficulty, 1);
|
|
|
|
// Past initial threshold, so no "until reduced" milestone
|
|
assert_eq!(response.assertions_until_reduced_difficulty, None);
|
|
// Still 25 assertions until exemption
|
|
assert_eq!(response.assertions_until_exemption, Some(25));
|
|
}
|
|
|
|
#[test]
|
|
fn test_all_tier_quotas() {
|
|
let config = AdmissionConfig::default();
|
|
|
|
// Test each tier
|
|
let test_cases = [
|
|
(0.1, TrustTierDto::Untrusted, 1_000),
|
|
(0.4, TrustTierDto::Limited, 5_000),
|
|
(0.5, TrustTierDto::Verified, 10_000),
|
|
(0.8, TrustTierDto::Trusted, 20_000),
|
|
(0.95, TrustTierDto::Authority, 100_000),
|
|
];
|
|
|
|
for (score, expected_tier, expected_quota) in test_cases {
|
|
let status = AdmissionStatus::new(score, 100, 0);
|
|
let response = AdmissionStatusResponse::from_status("test".to_string(), &status, &config);
|
|
|
|
assert_eq!(response.tier, expected_tier, "Wrong tier for score {}", score);
|
|
assert_eq!(
|
|
response.effective_quota_limit, expected_quota,
|
|
"Wrong quota for score {}",
|
|
score
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_pow_difficulty_graduation() {
|
|
let config = AdmissionConfig::default();
|
|
|
|
// First 10 assertions: 16 bits
|
|
for count in 0..10 {
|
|
let difficulty = config.compute_difficulty(count, 0.3);
|
|
assert_eq!(difficulty, 16, "Wrong difficulty for {} assertions", count);
|
|
}
|
|
|
|
// 10-49: 1 bit
|
|
for count in 10..50 {
|
|
let difficulty = config.compute_difficulty(count, 0.3);
|
|
assert_eq!(difficulty, 1, "Wrong difficulty for {} assertions", count);
|
|
}
|
|
|
|
// 50+: exempt
|
|
let difficulty = config.compute_difficulty(50, 0.3);
|
|
assert_eq!(difficulty, 0);
|
|
|
|
// Trust exemption
|
|
let difficulty = config.compute_difficulty(5, 0.6);
|
|
assert_eq!(difficulty, 0, "High trust should be exempt");
|
|
}
|