UNPKG

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

175 lines 5.76 kB
/** * Anonymization Pipeline * PII detection and redaction for pattern export */ import * as crypto from 'crypto'; /** * PII detection patterns */ const PII_PATTERNS = { email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, phone: /\b(\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g, ipv4: /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g, ipv6: /\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g, apiKey: /\b(sk-|pk-|api[_-]?key[_-]?)[a-zA-Z0-9]{20,}\b/gi, jwt: /\beyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*\b/g, homePath: /\/(Users|home|Documents)\/[a-zA-Z0-9_.-]+/g, windowsPath: /[A-Z]:\\Users\\[a-zA-Z0-9_.-]+/g, }; /** * Redaction replacements */ const REDACTIONS = { email: (match) => `user_${hash(match).slice(0, 8)}@example.com`, phone: '[REDACTED_PHONE]', ipv4: '0.0.0.0', ipv6: '::1', apiKey: '[REDACTED_API_KEY]', jwt: '[REDACTED_JWT]', homePath: '/user/anonymous', windowsPath: 'C:\\Users\\anonymous', }; /** * Hash a string for consistent pseudonymization */ function hash(input) { return crypto.createHash('sha256').update(input).digest('hex'); } /** * Detect PII in a string */ export function detectPII(content) { const result = { found: false, count: 0, types: {}, locations: [], }; for (const [type, pattern] of Object.entries(PII_PATTERNS)) { const matches = content.match(pattern); if (matches) { result.found = true; result.count += matches.length; result.types[type] = matches.length; for (const match of matches.slice(0, 5)) { // Limit to first 5 samples result.locations.push({ type, path: 'content', sample: match.slice(0, 20) + (match.length > 20 ? '...' : ''), severity: getSeverity(type), }); } } } return result; } /** * Get severity for PII type */ function getSeverity(type) { switch (type) { case 'apiKey': case 'jwt': return 'critical'; case 'email': case 'phone': return 'high'; case 'ipv4': case 'ipv6': return 'medium'; default: return 'low'; } } /** * Redact PII from a string */ export function redactPII(content) { let result = content; for (const [type, pattern] of Object.entries(PII_PATTERNS)) { const replacement = REDACTIONS[type]; if (typeof replacement === 'function') { result = result.replace(pattern, replacement); } else { result = result.replace(pattern, replacement); } } return result; } /** * Apply anonymization to CFP document */ export function anonymizeCFP(cfp, level) { const transforms = []; const anonymized = JSON.parse(JSON.stringify(cfp)); // Level: Minimal if (['minimal', 'standard', 'strict', 'paranoid'].includes(level)) { // Redact author display name if (anonymized.metadata.author?.displayName) { anonymized.metadata.author.displayName = undefined; transforms.push('author-name-removed'); } } // Level: Standard if (['standard', 'strict', 'paranoid'].includes(level)) { // Redact PII from all string fields const jsonStr = JSON.stringify(anonymized.patterns); const redacted = redactPII(jsonStr); anonymized.patterns = JSON.parse(redacted); transforms.push('pii-redacted'); // Generalize timestamps anonymized.anonymization.timestampsGeneralized = true; transforms.push('timestamps-generalized'); } // Level: Strict if (['strict', 'paranoid'].includes(level)) { // Hash all IDs for (const pattern of anonymized.patterns.routing) { pattern.id = `pattern_${hash(pattern.id).slice(0, 12)}`; } transforms.push('ids-hashed'); // Remove context details for (const pattern of anonymized.patterns.routing) { pattern.context = undefined; } transforms.push('context-removed'); anonymized.anonymization.pathsStripped = true; transforms.push('paths-stripped'); } // Level: Paranoid if (level === 'paranoid') { // Add noise to numeric values (differential privacy) for (const pattern of anonymized.patterns.routing) { pattern.usageCount = Math.round(pattern.usageCount * (0.9 + Math.random() * 0.2)); pattern.successRate = Math.min(1, Math.max(0, pattern.successRate + (Math.random() - 0.5) * 0.1)); } transforms.push('differential-privacy-noise'); // Remove all trajectory learnings for (const traj of anonymized.patterns.trajectory) { traj.learnings = []; } transforms.push('learnings-removed'); } // Update anonymization record anonymized.anonymization.level = level; anonymized.anonymization.appliedTransforms = transforms; anonymized.anonymization.piiRedacted = level !== 'minimal'; // Recalculate checksum const content = JSON.stringify({ magic: anonymized.magic, version: anonymized.version, metadata: anonymized.metadata, patterns: anonymized.patterns, }); anonymized.anonymization.checksum = hash(content); return { cfp: anonymized, transforms }; } /** * Scan CFP for PII without modification */ export function scanCFPForPII(cfp) { const content = JSON.stringify(cfp.patterns); return detectPII(content); } //# sourceMappingURL=index.js.map