claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
206 lines (163 loc) • 6.22 kB
text/typescript
import { TrustLevel, TRUST_TRANSITION_THRESHOLDS } from '../domain/entities/trust-level.js';
import { FederationNode } from '../domain/entities/federation-node.js';
import { type SessionMetrics } from '../domain/entities/federation-session.js';
export interface TrustScoreComponents {
readonly successRate: number;
readonly uptime: number;
readonly threatPenalty: number;
readonly dataIntegrityScore: number;
}
export interface TrustTransitionResult {
readonly previousLevel: TrustLevel;
readonly newLevel: TrustLevel;
readonly score: number;
readonly components: TrustScoreComponents;
readonly reason: string;
readonly requiresHumanApproval: boolean;
}
export type ImmediateDowngradeReason =
| 'repeated-threat-detection'
| 'hmac-verification-failure'
| 'session-hijack-attempt';
export interface TrustEvaluatorDeps {
onTrustChange?: (nodeId: string, result: TrustTransitionResult) => void;
}
export interface ThreatWindow {
readonly detections: Date[];
readonly windowMs: number;
readonly threshold: number;
}
const THREAT_WINDOW_CONFIG: ThreatWindow = {
detections: [],
windowMs: 3_600_000,
threshold: 2,
};
export class TrustEvaluator {
private readonly deps: TrustEvaluatorDeps;
private readonly threatWindows: Map<string, Date[]>;
constructor(deps: TrustEvaluatorDeps = {}) {
this.deps = deps;
this.threatWindows = new Map();
}
computeScore(metrics: SessionMetrics, uptimeRatio: number): { score: number; components: TrustScoreComponents } {
const totalAttempted = metrics.messagesSent + metrics.messagesReceived;
const successRate = totalAttempted > 0
? (totalAttempted - metrics.hmacFailures) / totalAttempted
: 0;
const uptime = Math.max(0, Math.min(1, uptimeRatio));
const threatPenalty = this.computeThreatPenalty(metrics.threatDetections, totalAttempted);
const dataIntegrityScore = totalAttempted > 0
? 1 - (metrics.hmacFailures / totalAttempted)
: 1;
const score =
0.4 * successRate +
0.2 * uptime +
0.2 * (1 - threatPenalty) +
0.2 * dataIntegrityScore;
const components: TrustScoreComponents = {
successRate,
uptime,
threatPenalty,
dataIntegrityScore,
};
return { score: Math.max(0, Math.min(1, score)), components };
}
evaluateTransition(
node: FederationNode,
metrics: SessionMetrics,
uptimeRatio: number,
hasInstitutionalAttestation: boolean = false,
): TrustTransitionResult | null {
const { score, components } = this.computeScore(metrics, uptimeRatio);
const currentLevel = node.trustLevel;
node.updateTrustScore(score);
const upgrade = this.checkUpgrade(currentLevel, score, metrics.totalInteractions, hasInstitutionalAttestation);
if (upgrade !== null) {
const result: TrustTransitionResult = {
previousLevel: currentLevel,
newLevel: upgrade,
score,
components,
reason: `Score ${score.toFixed(3)} meets upgrade threshold for level ${upgrade}`,
requiresHumanApproval: upgrade === TrustLevel.PRIVILEGED,
};
if (!result.requiresHumanApproval) {
node.updateTrustLevel(upgrade);
}
this.deps.onTrustChange?.(node.nodeId, result);
return result;
}
const downgrade = this.checkDowngrade(currentLevel, score);
if (downgrade !== null) {
const result: TrustTransitionResult = {
previousLevel: currentLevel,
newLevel: downgrade,
score,
components,
reason: `Score ${score.toFixed(3)} dropped below downgrade threshold for level ${currentLevel}`,
requiresHumanApproval: false,
};
node.updateTrustLevel(downgrade);
this.deps.onTrustChange?.(node.nodeId, result);
return result;
}
return null;
}
downgrade(node: FederationNode, reason: ImmediateDowngradeReason): TrustTransitionResult {
const previousLevel = node.trustLevel;
node.updateTrustLevel(TrustLevel.UNTRUSTED);
node.updateTrustScore(0);
const result: TrustTransitionResult = {
previousLevel,
newLevel: TrustLevel.UNTRUSTED,
score: 0,
components: { successRate: 0, uptime: 0, threatPenalty: 1, dataIntegrityScore: 0 },
reason: `Immediate downgrade: ${reason}`,
requiresHumanApproval: false,
};
this.deps.onTrustChange?.(node.nodeId, result);
return result;
}
recordThreatDetection(nodeId: string): boolean {
const now = new Date();
const detections = this.threatWindows.get(nodeId) ?? [];
detections.push(now);
const windowStart = now.getTime() - THREAT_WINDOW_CONFIG.windowMs;
const recentDetections = detections.filter(d => d.getTime() > windowStart);
this.threatWindows.set(nodeId, recentDetections);
return recentDetections.length >= THREAT_WINDOW_CONFIG.threshold;
}
private checkUpgrade(
currentLevel: TrustLevel,
score: number,
totalInteractions: number,
hasInstitutionalAttestation: boolean,
): TrustLevel | null {
if (currentLevel >= TrustLevel.PRIVILEGED) return null;
const nextLevel = currentLevel + 1;
const transitionKey = `${currentLevel}->${nextLevel}`;
const threshold = TRUST_TRANSITION_THRESHOLDS[transitionKey];
if (!threshold) return null;
if (score < threshold.upgradeScore) return null;
if (totalInteractions < threshold.minInteractions) return null;
if (nextLevel === TrustLevel.PRIVILEGED && !hasInstitutionalAttestation) {
return null;
}
return nextLevel as TrustLevel;
}
private checkDowngrade(currentLevel: TrustLevel, score: number): TrustLevel | null {
if (currentLevel <= TrustLevel.UNTRUSTED) return null;
const transitionKey = `${currentLevel - 1}->${currentLevel}`;
const threshold = TRUST_TRANSITION_THRESHOLDS[transitionKey];
if (!threshold) return null;
if (score < threshold.downgradeScore) {
return (currentLevel - 1) as TrustLevel;
}
return null;
}
private computeThreatPenalty(threatCount: number, totalMessages: number): number {
if (totalMessages === 0) return 0;
const ratio = threatCount / totalMessages;
return Math.min(1, ratio * 10);
}
}