Proper dahsboard for rish analysis

This commit is contained in:
2025-11-07 22:59:28 +05:30
parent 71206d5499
commit 0c45d3717c
3 changed files with 840 additions and 149 deletions

View File

@@ -117,6 +117,7 @@ class ReportGenerator:
privacy = self.risk_results.get('privacy_risks', {})
return {
'pii_detected': privacy.get('pii_detected', []), # Include full PII detections array
'pii_count': len(privacy.get('pii_detected', [])),
'anonymization_level': privacy.get('anonymization_level', 'UNKNOWN'),
'exposure_risk_count': len(privacy.get('exposure_risks', [])),

View File

@@ -123,10 +123,14 @@ async def analyze_dataset(file: UploadFile = File(...)):
},
"risk_assessment": {
"overall_risk_score": risk_assessment.get("overall_risk_score", 0),
"privacy_risks": risk_assessment.get("privacy_risks", []),
"ethical_risks": risk_assessment.get("ethical_risks", []),
"compliance_risks": risk_assessment.get("risk_categories", {}).get("compliance_risks", []),
"data_quality_risks": risk_assessment.get("risk_categories", {}).get("data_quality_risks", [])
"risk_level": risk_assessment.get("risk_level", "LOW"),
"presidio_enabled": risk_assessment.get("presidio_enabled", False),
"privacy_risks": risk_assessment.get("privacy_risks", {}),
"ethical_risks": risk_assessment.get("ethical_risks", {}),
"compliance_risks": risk_assessment.get("compliance_risks", {}),
"risk_categories": risk_assessment.get("risk_categories", {}),
"violations": risk_assessment.get("violations", []),
"insights": risk_assessment.get("insights", [])
},
"recommendations": report.get("recommendations", []),
"report_file": f"/{report_path}",

View File

@@ -679,29 +679,113 @@ export function CenterPanel({ tab, onAnalyze }: CenterPanelProps) {
<span></span>
Fairness Violations Detected
</h3>
<div className="space-y-3">
{analyzeResult.bias_metrics.violations_detected.map((violation: any, i: number) => (
<div key={i} className="p-4 bg-white rounded-lg border border-red-200">
<div className="flex items-start gap-3">
<span className={`px-2 py-1 rounded text-xs font-bold ${
<div className="space-y-4">
{analyzeResult.bias_metrics.violations_detected.map((violation: any, i: number) => {
// Map bias violations to relevant GDPR articles
const gdprArticles = [
{
article: 'Article 5(1)(a) - Lawfulness, Fairness, and Transparency',
explanation: 'Personal data must be processed fairly. Algorithmic bias violates the fairness principle.'
},
{
article: 'Article 22 - Automated Decision-Making',
explanation: 'Individuals have the right not to be subject to decisions based solely on automated processing that produce legal or similarly significant effects, especially if discriminatory.'
},
{
article: 'Recital 71 - Safeguards Against Discrimination',
explanation: 'Automated decision-making should not be based on special categories of data and should include safeguards to prevent discriminatory effects.'
}
];
// Add ECOA if dealing with credit/lending
const isCredit = violation.attribute && (
violation.attribute.toLowerCase().includes('credit') ||
violation.attribute.toLowerCase().includes('loan') ||
violation.attribute.toLowerCase().includes('income')
);
return (
<div key={i} className="p-5 bg-white rounded-xl border-2 border-red-300 shadow-sm hover:shadow-md transition-all">
{/* Violation Header */}
<div className="flex items-start gap-3 mb-4">
<span className={`px-3 py-1 rounded-full text-xs font-black shadow-sm ${
violation.severity === 'HIGH' ? 'bg-red-600 text-white' :
violation.severity === 'MEDIUM' ? 'bg-orange-500 text-white' :
'bg-yellow-500 text-white'
violation.severity === 'MEDIUM' ? 'bg-orange-600 text-white' :
'bg-yellow-600 text-white'
}`}>
{violation.severity}
</span>
<div className="flex-1">
<div className="font-semibold text-slate-900">{violation.attribute}: {violation.metric}</div>
<div className="font-bold text-lg text-slate-900">
{violation.attribute}: {violation.metric}
</div>
<div className="text-sm text-slate-700 mt-1">{violation.message}</div>
</div>
</div>
{/* Violation Details */}
{violation.details && (
<div className="text-xs text-slate-500 mt-2 p-2 bg-slate-50 rounded">
{violation.details}
<div className="mb-4 p-3 bg-slate-50 rounded-lg border border-slate-200">
<div className="text-xs font-semibold text-slate-600 mb-1">📊 TECHNICAL DETAILS</div>
<div className="text-sm text-slate-700">{violation.details}</div>
</div>
)}
{/* GDPR Articles Violated */}
<div className="mb-4 p-4 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-lg border border-blue-200">
<div className="text-xs font-bold text-blue-800 mb-3 flex items-center gap-2">
<span></span>
GDPR ARTICLES VIOLATED
</div>
<div className="space-y-2">
{gdprArticles.map((gdpr, idx) => (
<div key={idx} className="p-2 bg-white/70 rounded border border-blue-200">
<div className="font-semibold text-xs text-blue-900">{gdpr.article}</div>
<div className="text-xs text-slate-700 mt-1">{gdpr.explanation}</div>
</div>
))}
{isCredit && (
<div className="p-2 bg-white/70 rounded border border-orange-200">
<div className="font-semibold text-xs text-orange-900">ECOA (Equal Credit Opportunity Act)</div>
<div className="text-xs text-slate-700 mt-1">
Prohibits discrimination in credit decisions based on protected characteristics. This bias violation may constitute illegal discrimination.
</div>
</div>
)}
</div>
</div>
{/* Recommendations */}
<div className="p-3 bg-gradient-to-r from-green-50 to-emerald-50 rounded-lg border border-green-200">
<div className="text-xs font-semibold text-green-800 mb-2"> RECOMMENDED ACTIONS</div>
<ul className="text-sm text-slate-700 space-y-1">
<li className="flex items-start gap-2">
<span className="text-green-600"></span>
<span>Investigate and remediate bias in the {violation.attribute} attribute</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600"></span>
<span>Implement fairness constraints during model training</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600"></span>
<span>Consider rebalancing dataset or applying bias mitigation techniques</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600"></span>
<span>Document fairness assessment in GDPR Article 35 DPIA (Data Protection Impact Assessment)</span>
</li>
{violation.severity === 'HIGH' && (
<li className="flex items-start gap-2">
<span className="text-red-600"></span>
<span className="text-red-700 font-semibold">URGENT: This high-severity violation requires immediate attention before deployment</span>
</li>
)}
</ul>
</div>
))}
</div>
);
})}
</div>
</div>
)}
@@ -892,101 +976,515 @@ export function CenterPanel({ tab, onAnalyze }: CenterPanelProps) {
</div>
</div>
{/* Privacy Risks - PII Detection */}
{/* Risky Features Analysis - Feature-Level Risk Display */}
{analyzeResult.risk_assessment.privacy_risks && (
<div className="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-sm">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🔒</span>
<h3 className="text-lg font-bold text-slate-800">Privacy Risks</h3>
<span className="ml-auto px-3 py-1 bg-slate-100 text-slate-700 rounded-full text-xs font-semibold">
<div className="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-lg">
<div className="flex items-center gap-2 mb-6">
<span className="text-2xl"></span>
<h3 className="text-xl font-bold text-slate-800">Risky Features & Columns</h3>
<span className="ml-auto px-3 py-1 bg-red-100 text-red-700 rounded-full text-xs font-semibold">
{typeof analyzeResult.risk_assessment.privacy_risks === 'object' && !Array.isArray(analyzeResult.risk_assessment.privacy_risks)
? (analyzeResult.risk_assessment.privacy_risks.pii_count || 0)
: (Array.isArray(analyzeResult.risk_assessment.privacy_risks) ? analyzeResult.risk_assessment.privacy_risks.length : 0)} PII Types
: (Array.isArray(analyzeResult.risk_assessment.privacy_risks) ? analyzeResult.risk_assessment.privacy_risks.length : 0)} Risky Features Found
</span>
</div>
{/* PII Detections - Handle both object and array formats */}
{/* Risky Features List */}
{(typeof analyzeResult.risk_assessment.privacy_risks === 'object' &&
!Array.isArray(analyzeResult.risk_assessment.privacy_risks) &&
analyzeResult.risk_assessment.privacy_risks.pii_detected &&
analyzeResult.risk_assessment.privacy_risks.pii_detected.length > 0) ? (
<div className="space-y-3">
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{analyzeResult.risk_assessment.privacy_risks.pii_detected.slice(0, 6).map((pii: any, idx: number) => (
<div key={idx} className={`p-3 rounded-lg border-2 ${
pii.severity === 'CRITICAL' ? 'bg-red-50 border-red-200' :
pii.severity === 'HIGH' ? 'bg-orange-50 border-orange-200' :
pii.severity === 'MEDIUM' ? 'bg-yellow-50 border-yellow-200' :
'bg-blue-50 border-blue-200'
<div className="space-y-4">
{/* Privacy Risk Metrics Summary */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 p-4 bg-gradient-to-br from-red-50 to-orange-50 rounded-lg border-2 border-red-200">
<div className="text-center">
<div className="text-xs text-slate-600 mb-1 font-semibold">Re-Identification Risk</div>
<div className={`text-3xl font-black ${
(analyzeResult.risk_assessment.privacy_risks.reidentification_risk || 0) > 0.7 ? 'text-red-600' :
(analyzeResult.risk_assessment.privacy_risks.reidentification_risk || 0) > 0.4 ? 'text-orange-600' :
'text-green-600'
}`}>
<div className="flex items-center justify-between mb-1">
<span className="text-xs font-bold text-slate-600">
{pii.column}
</span>
<span className={`text-xs font-bold px-2 py-0.5 rounded ${
pii.severity === 'CRITICAL' ? 'bg-red-100 text-red-700' :
pii.severity === 'HIGH' ? 'bg-orange-100 text-orange-700' :
pii.severity === 'MEDIUM' ? 'bg-yellow-100 text-yellow-700' :
'bg-blue-100 text-blue-700'
}`}>
{pii.severity}
</span>
</div>
<div className="text-sm font-semibold text-slate-800">
{pii.type}
</div>
<div className="text-xs text-slate-600 mt-1">
Detected via: {pii.detection_method}
{pii.confidence && ` (${(pii.confidence * 100).toFixed(0)}% confidence)`}
</div>
</div>
))}
</div>
{/* Privacy Metrics */}
{typeof analyzeResult.risk_assessment.privacy_risks === 'object' &&
!Array.isArray(analyzeResult.risk_assessment.privacy_risks) && (
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 pt-3 border-t border-slate-200">
<div className="text-center p-3 bg-slate-50 rounded-lg">
<div className="text-xs text-slate-600 mb-1">Re-ID Risk</div>
<div className="text-lg font-bold text-slate-800">
{analyzeResult.risk_assessment.privacy_risks.reidentification_risk
? (analyzeResult.risk_assessment.privacy_risks.reidentification_risk * 100).toFixed(0)
: 0}%
</div>
<div className="text-xs text-slate-500 mt-1">Can individuals be identified?</div>
</div>
<div className="text-center p-3 bg-slate-50 rounded-lg">
<div className="text-xs text-slate-600 mb-1">Data Minimization</div>
<div className="text-lg font-bold text-slate-800">
<div className="text-center">
<div className="text-xs text-slate-600 mb-1 font-semibold">Data Minimization</div>
<div className={`text-3xl font-black ${
(analyzeResult.risk_assessment.privacy_risks.data_minimization_score || 0) > 0.7 ? 'text-green-600' :
(analyzeResult.risk_assessment.privacy_risks.data_minimization_score || 0) > 0.4 ? 'text-orange-600' :
'text-red-600'
}`}>
{analyzeResult.risk_assessment.privacy_risks.data_minimization_score
? (analyzeResult.risk_assessment.privacy_risks.data_minimization_score * 100).toFixed(0)
: 0}%
</div>
<div className="text-xs text-slate-500 mt-1">Collecting only necessary data</div>
</div>
<div className="text-center p-3 bg-slate-50 rounded-lg">
<div className="text-xs text-slate-600 mb-1">Anonymization</div>
<div className="text-sm font-bold text-slate-800">
{analyzeResult.risk_assessment.privacy_risks.anonymization_level || 'N/A'}
<div className="text-center">
<div className="text-xs text-slate-600 mb-1 font-semibold">Anonymization Level</div>
<div className={`text-sm font-black px-3 py-1 rounded-full inline-block ${
analyzeResult.risk_assessment.privacy_risks.anonymization_level === 'FULL' ? 'bg-green-100 text-green-700' :
analyzeResult.risk_assessment.privacy_risks.anonymization_level === 'PARTIAL' ? 'bg-yellow-100 text-yellow-700' :
'bg-red-100 text-red-700'
}`}>
{analyzeResult.risk_assessment.privacy_risks.anonymization_level || 'NONE'}
</div>
<div className="text-xs text-slate-500 mt-1">Protection applied</div>
</div>
<div className="text-center p-3 bg-slate-50 rounded-lg">
<div className="text-xs text-slate-600 mb-1">Detection</div>
<div className="text-sm font-bold text-slate-800">
<div className="text-center">
<div className="text-xs text-slate-600 mb-1 font-semibold">Detection Method</div>
<div className="text-sm font-bold text-slate-800 px-3 py-1 bg-white rounded border-2 border-slate-300 inline-block">
{analyzeResult.risk_assessment.privacy_risks.detection_method || 'Auto'}
</div>
<div className="text-xs text-slate-500 mt-1">Analysis engine used</div>
</div>
</div>
{/* Individual Risky Features */}
<div className="space-y-3">
<h4 className="font-bold text-slate-700 flex items-center gap-2">
<span>🔍</span> Detailed Feature Risk Analysis
</h4>
{analyzeResult.risk_assessment.privacy_risks.pii_detected.map((pii: any, idx: number) => {
// Map PII types to risk explanations with GDPR Article references
const riskExplanations: Record<string, { why: string; impact: string; gdprArticles: string[]; actions: string[] }> = {
'EMAIL_ADDRESS': {
why: 'Email addresses are direct identifiers that can be used to contact and track individuals across systems, creating privacy risks.',
impact: 'HIGH RISK: Can lead to identity theft, phishing attacks, unauthorized marketing, and privacy violations under GDPR Article 6.',
gdprArticles: [
'Article 4(1) - Definition of Personal Data: Email is personally identifiable information',
'Article 6 - Lawful Basis Required: Processing requires consent, contract, or legitimate interest',
'Article 7 - Consent Conditions: Must obtain explicit, informed consent',
'Article 17 - Right to Erasure: Users can request email deletion',
'Article 21 - Right to Object: Users can opt out of email processing'
],
actions: ['Encrypt email addresses', 'Hash or pseudonymize for analytics', 'Implement consent management', 'Enable right to erasure', 'Provide opt-out mechanisms']
},
'EMAIL': {
why: 'Email addresses are direct identifiers that can be used to contact and track individuals across systems.',
impact: 'HIGH RISK: Can lead to identity theft, phishing attacks, unauthorized marketing, and privacy violations.',
gdprArticles: [
'Article 4(1) - Personal Data Definition',
'Article 6 - Lawful Basis for Processing',
'Article 7 - Conditions for Consent',
'Article 17 - Right to Erasure'
],
actions: ['Encrypt email addresses', 'Implement consent management', 'Enable deletion on request', 'Apply data minimization']
},
'PHONE_NUMBER': {
why: 'Phone numbers directly identify individuals and enable real-time contact, creating opportunities for harassment and fraud.',
impact: 'HIGH RISK: Enables unwanted contact, harassment, SIM swapping attacks, location tracking, and telemarketing violations.',
gdprArticles: [
'Article 4(1) - Personal Data: Phone numbers identify natural persons',
'Article 6 - Lawfulness of Processing: Requires lawful basis',
'Article 32 - Security of Processing: Must implement appropriate security measures',
'Article 21 - Right to Object to Processing',
'ePrivacy Directive - Consent required for electronic communications'
],
actions: ['Remove if not essential', 'Apply tokenization', 'Restrict access controls', 'Implement call verification', 'Enable number suppression']
},
'PHONE': {
why: 'Phone numbers are direct personal identifiers enabling contact and tracking.',
impact: 'HIGH RISK: Harassment, fraud, and unauthorized marketing.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 6 - Lawful Processing',
'Article 32 - Security Measures'
],
actions: ['Tokenize phone numbers', 'Implement access controls', 'Enable opt-out']
},
'PERSON': {
why: 'Personal names are primary identifiers. Combined with other quasi-identifiers (age, location), they enable complete re-identification.',
impact: 'MEDIUM-HIGH RISK: When combined with location, age, or other quasi-identifiers, creates high re-identification risk violating k-anonymity.',
gdprArticles: [
'Article 4(1) - Personal Data: Names identify natural persons',
'Article 5(1)(c) - Data Minimization: Collect only necessary data',
'Article 5(1)(e) - Storage Limitation: Keep only as long as necessary',
'Article 25 - Data Protection by Design and Default',
'Article 32(1)(a) - Pseudonymization and encryption requirements'
],
actions: ['Use pseudonyms or IDs', 'Apply k-anonymity techniques (k≥5)', 'Separate name from sensitive attributes', 'Implement access logging', 'Apply l-diversity for protection']
},
'NAME': {
why: 'Names are direct personal identifiers that enable individual identification.',
impact: 'MEDIUM-HIGH RISK: Re-identification when combined with other data.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 5(1)(c) - Data Minimization',
'Article 25 - Data Protection by Design'
],
actions: ['Use pseudonyms', 'Apply k-anonymity', 'Implement access logging']
},
'LOCATION': {
why: 'Location data reveals where individuals live, work, and travel, exposing personal patterns, habits, and sensitive locations (hospitals, religious sites).',
impact: 'HIGH RISK: Can expose home addresses, workplaces, medical facilities, places of worship, creating discrimination and stalking risks.',
gdprArticles: [
'Article 4(1) - Personal Data: Location identifies individuals',
'Article 9(1) - Special Categories: Location at sensitive sites reveals protected characteristics',
'Article 32 - Security Measures: Encryption and access controls required',
'Article 35 - Data Protection Impact Assessment: Required for location tracking',
'Recital 30 - Online identifiers and location data'
],
actions: ['Generalize to zip code or city level', 'Apply geographic masking', 'Remove precise coordinates', 'Implement geofencing', 'Conduct DPIA', 'Apply differential privacy']
},
'ADDRESS': {
why: 'Physical addresses directly identify individuals and their home locations.',
impact: 'HIGH RISK: Enables stalking, burglary, and privacy violations.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 9 - Special Categories (if sensitive location)',
'Article 32 - Security Measures'
],
actions: ['Generalize to zip code', 'Apply geographic masking', 'Restrict access']
},
'SSN': {
why: 'Social Security Numbers are PERMANENT unique identifiers used across critical systems (banking, taxes, healthcare, employment).',
impact: 'CRITICAL RISK: Enables complete identity theft, fraudulent credit, tax fraud, medical identity theft, and unauthorized government benefits access.',
gdprArticles: [
'Article 9(1) - Special Category Data: Often linked to health/financial data',
'Article 32 - Security of Processing: Encryption, access controls, pseudonymization mandatory',
'Article 33 - Breach Notification: Immediate notification required',
'Article 34 - Data Subject Notification: Notify individuals of breaches',
'Article 35 - Data Protection Impact Assessment: DPIA required',
'Recital 75 - High risk to rights and freedoms'
],
actions: ['REMOVE IMMEDIATELY if possible', 'Encrypt with AES-256', 'Never display in full', 'Implement strict access controls', 'Conduct DPIA', 'Enable breach detection', 'Maintain audit logs']
},
'US_SSN': {
why: 'US Social Security Numbers are permanent government identifiers linked to financial, medical, employment, and government benefits.',
impact: 'CRITICAL RISK: Highest identity theft risk. Compromise leads to decades of fraud, financial damage, and cannot be changed.',
gdprArticles: [
'Article 9(1) - Special Category: Links to health and financial data',
'Article 32 - Security Measures: State-of-the-art encryption required',
'Article 33 - Breach Notification: 72-hour notification to supervisory authority',
'Article 34 - Communication to Data Subjects: Immediate notification',
'Article 35 - DPIA: Mandatory impact assessment'
],
actions: ['Encrypt end-to-end with AES-256', 'Use last 4 digits only for display', 'Implement multi-factor authentication', 'Enable breach detection', 'Create comprehensive audit trails', 'Apply tokenization', 'Conduct annual security audits']
},
'CREDIT_CARD': {
why: 'Credit card numbers provide direct access to financial accounts and purchasing power, subject to PCI-DSS and GDPR.',
impact: 'CRITICAL RISK: Financial fraud, unauthorized transactions, PCI-DSS violations (fines up to $500K/month), GDPR violations (4% global revenue).',
gdprArticles: [
'Article 4(1) - Personal Data: Financial identifiers',
'Article 32 - Security of Processing: PCI-DSS Level 1 compliance mandatory',
'Article 33 - Breach Notification: Immediate reporting required',
'Article 34 - Data Subject Notification',
'PCI-DSS Standards: Cannot store CVV, must tokenize'
],
actions: ['Tokenize immediately', 'Never store CVV/CVC', 'Use PCI-compliant vault', 'Implement fraud detection', 'Apply end-to-end encryption', 'Use 3D Secure', 'Maintain PCI-DSS certification', 'Conduct quarterly security scans']
},
'CARD': {
why: 'Card numbers enable direct financial access.',
impact: 'CRITICAL RISK: Financial fraud and PCI-DSS violations.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 32 - Security Measures',
'PCI-DSS Compliance'
],
actions: ['Tokenize immediately', 'Use PCI-compliant vault', 'Never store CVV']
},
'IP_ADDRESS': {
why: 'IP addresses are online identifiers that track user behavior, reveal location, and enable device fingerprinting across websites.',
impact: 'MEDIUM RISK: Enables tracking across websites, reveals approximate location, can be linked to individuals, violates ePrivacy Directive.',
gdprArticles: [
'Article 4(1) - Personal Data: Online identifier',
'Article 6 - Lawful Basis: Requires consent or legitimate interest',
'ePrivacy Directive - Consent for cookies and tracking',
'Recital 30 - Online identifiers and IP addresses',
'Article 21 - Right to Object to profiling'
],
actions: ['Truncate last octet for IPv4', 'Hash for analytics', 'Implement IP anonymization', 'Reduce retention period to 90 days', 'Provide opt-out for tracking', 'Apply differential privacy']
},
'IP': {
why: 'IP addresses are online identifiers enabling tracking.',
impact: 'MEDIUM RISK: Cross-site tracking and location revelation.',
gdprArticles: [
'Article 4(1) - Online Identifier',
'Article 6 - Lawful Basis',
'ePrivacy Directive'
],
actions: ['Truncate IP addresses', 'Hash for analytics', 'Reduce retention']
},
'MEDICAL_LICENSE': {
why: 'Medical information is SPECIAL CATEGORY DATA under GDPR Article 9, requiring the highest level of protection due to discrimination risks.',
impact: 'CRITICAL RISK: Health data breach leads to discrimination, insurance denial, employment issues, severe privacy violations, and HIPAA fines.',
gdprArticles: [
'Article 9(1) - Special Category (Health Data): Explicit consent required',
'Article 9(2)(h) - Health/social care exception',
'Article 32 - Security of Processing: Encryption mandatory',
'Article 35 - DPIA: Impact assessment required',
'Article 25 - Data Protection by Design',
'HIPAA Compliance (if applicable)'
],
actions: ['Encrypt with healthcare-grade security (AES-256)', 'Implement role-based access control (RBAC)', 'Conduct Data Protection Impact Assessment', 'Apply strict retention policies', 'Ensure HIPAA compliance', 'Use de-identification techniques', 'Maintain comprehensive audit logs']
},
'MEDICAL': {
why: 'Medical data is special category data requiring explicit consent.',
impact: 'CRITICAL RISK: Discrimination and severe privacy violations.',
gdprArticles: [
'Article 9(1) - Special Category (Health)',
'Article 32 - Security',
'Article 35 - DPIA Required'
],
actions: ['Encrypt data', 'Implement RBAC', 'Conduct DPIA']
},
'US_DRIVER_LICENSE': {
why: 'Driver license numbers are government-issued identifiers used for identity verification across financial, healthcare, and government systems.',
impact: 'HIGH RISK: Identity fraud, fake ID creation, unauthorized access to services, and DMV record access.',
gdprArticles: [
'Article 4(1) - Personal Data: Government identifier',
'Article 6 - Lawful Processing: Document lawful basis',
'Article 32 - Security Measures: Encryption and access controls',
'Article 15 - Right of Access: Individuals can request data',
'Article 17 - Right to Erasure: Deletion on request'
],
actions: ['Hash or encrypt license numbers', 'Limit to identity verification only', 'Never display in full', 'Implement verification logging', 'Apply pseudonymization', 'Enable deletion mechanisms']
},
'LICENSE': {
why: 'License numbers are government identifiers.',
impact: 'HIGH RISK: Identity fraud and unauthorized access.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 6 - Lawful Processing',
'Article 32 - Security'
],
actions: ['Hash license numbers', 'Limit to verification', 'Never display in full']
},
'US_PASSPORT': {
why: 'Passport numbers are international identity documents used for travel and high-security identification, recognized globally.',
impact: 'CRITICAL RISK: International identity fraud, unauthorized travel booking, visa fraud, and access to secure facilities.',
gdprArticles: [
'Article 4(1) - Personal Data: Unique government identifier',
'Article 32 - Security Measures: State-of-the-art encryption required',
'Article 35 - Impact Assessment: DPIA for high-risk processing',
'Article 5(1)(f) - Integrity and Confidentiality',
'Cross-border data transfer regulations'
],
actions: ['Encrypt with strong encryption (AES-256)', 'Restrict access to authorized personnel only', 'Implement tamper detection', 'Apply geographic access controls', 'Maintain detailed audit trails', 'Use tokenization', 'Implement MFA for access']
},
'PASSPORT': {
why: 'Passport numbers enable international identification.',
impact: 'CRITICAL RISK: International fraud and unauthorized travel.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 32 - Security Measures',
'Article 35 - Impact Assessment'
],
actions: ['Encrypt passports', 'Restrict access', 'Implement tamper detection']
},
'US_BANK_NUMBER': {
why: 'Bank account numbers provide DIRECT ACCESS to financial accounts and enable ACH transfers, wire transfers, and direct debits.',
impact: 'CRITICAL RISK: Unauthorized withdrawals, ACH fraud, wire transfer fraud, complete account takeover, and financial ruin.',
gdprArticles: [
'Article 4(1) - Personal Data: Financial identifier',
'Article 32 - Security Measures: Encryption and tokenization mandatory',
'Article 33 - Breach Notification: 72-hour notification',
'Article 34 - Data Subject Notification: Immediate alert to account holders',
'PSD2 - Strong Customer Authentication required'
],
actions: ['Tokenize immediately', 'Never display account numbers', 'Use secure payment gateways', 'Implement transaction monitoring', 'Apply multi-factor authentication', 'Use Strong Customer Authentication (SCA)', 'Enable fraud alerts', 'Encrypt at rest and in transit']
},
'BANK_ACCOUNT': {
why: 'Bank account numbers enable direct financial access.',
impact: 'CRITICAL RISK: Financial fraud and account takeover.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 32 - Security Measures',
'Article 33 - Breach Notification'
],
actions: ['Tokenize accounts', 'Never display numbers', 'Implement MFA']
},
'DOB': {
why: 'Date of birth is a quasi-identifier that combined with other data enables re-identification and age-based discrimination.',
impact: 'MEDIUM-HIGH RISK: Combined with name and zip code, enables 87% re-identification rate. Age discrimination risk.',
gdprArticles: [
'Article 4(1) - Personal Data: Quasi-identifier',
'Article 5(1)(c) - Data Minimization: Use age ranges instead',
'Article 9 - Special Categories: Can reveal protected characteristics',
'Article 22 - Automated Decision-Making: Age-based profiling restrictions',
'Recital 26 - Pseudonymization reduces risks'
],
actions: ['Use age ranges instead of exact DOB', 'Apply k-anonymity (k≥5)', 'Generalize to year or month', 'Separate from other identifiers', 'Implement access controls', 'Apply l-diversity']
},
'ZIP_CODE': {
why: 'ZIP codes are geographic quasi-identifiers. Research shows 87% of US population uniquely identified by ZIP + DOB + Gender.',
impact: 'MEDIUM RISK: When combined with DOB and gender, enables 87% re-identification. Reveals socioeconomic status and demographics.',
gdprArticles: [
'Article 4(1) - Personal Data: Quasi-identifier',
'Article 5(1)(c) - Data Minimization',
'Article 32(1)(a) - Pseudonymization',
'Recital 26 - Anonymization techniques',
'Article 25 - Data Protection by Default'
],
actions: ['Generalize to first 3 digits', 'Use geographic aggregation', 'Apply k-anonymity', 'Combine with other anonymization techniques', 'Separate from name and DOB']
},
'IBAN_CODE': {
why: 'IBAN (International Bank Account Number) provides access to bank accounts across European Economic Area.',
impact: 'CRITICAL RISK: International financial fraud, SEPA direct debit fraud, and cross-border money theft.',
gdprArticles: [
'Article 4(1) - Personal Data',
'Article 32 - Security of Processing',
'Article 33 - Breach Notification',
'PSD2 - Strong Customer Authentication'
],
actions: ['Tokenize IBAN', 'Implement SCA', 'Use secure payment processors', 'Enable fraud monitoring', 'Apply encryption']
},
'CRYPTO': {
why: 'Cryptocurrency addresses and wallets are permanent financial identifiers that cannot be changed if compromised.',
impact: 'CRITICAL RISK: Irreversible financial theft, no fraud protection, transaction history exposure, wallet draining.',
gdprArticles: [
'Article 4(1) - Personal Data: Cryptocurrency addresses can identify individuals',
'Article 5(1)(f) - Security Principle',
'Article 32 - Security Measures: Multi-signature and cold storage',
'Article 17 - Right to Erasure: Blockchain immutability challenges'
],
actions: ['Use multi-signature wallets', 'Implement cold storage', 'Never display private keys', 'Use hardware security modules', 'Apply address rotation', 'Implement withdrawal limits']
}
};
// Fallback for unmapped PII types
const riskInfo = riskExplanations[pii.type] || riskExplanations[pii.type.toUpperCase()] || {
why: 'This data type contains personal information that could identify individuals or reveal sensitive patterns according to GDPR Article 4(1).',
impact: 'POTENTIAL RISK: May violate privacy regulations if not properly protected. Could enable tracking, profiling, or discrimination.',
gdprArticles: [
'Article 4(1) - Definition of Personal Data',
'Article 5 - Principles: Lawfulness, Fairness, Transparency',
'Article 6 - Lawful Basis Required for Processing',
'Article 24 - Responsibility of the Controller',
'Article 25 - Data Protection by Design and Default'
],
actions: ['Review necessity of this data field', 'Apply appropriate anonymization techniques', 'Implement access controls and audit logging', 'Document lawful basis for processing', 'Conduct Privacy Impact Assessment']
};
return (
<div key={idx} className={`group relative overflow-hidden rounded-xl border-2 p-6 transition-all hover:shadow-xl ${
pii.severity === 'CRITICAL' ? 'bg-gradient-to-br from-red-50 via-white to-red-100 border-red-400' :
pii.severity === 'HIGH' ? 'bg-gradient-to-br from-orange-50 via-white to-orange-100 border-orange-400' :
pii.severity === 'MEDIUM' ? 'bg-gradient-to-br from-yellow-50 via-white to-yellow-100 border-yellow-400' :
'bg-gradient-to-br from-blue-50 via-white to-blue-100 border-blue-400'
}`}>
<div className="absolute top-0 right-0 w-40 h-40 bg-white/30 rounded-full blur-3xl"></div>
<div className="relative">
{/* Feature Header */}
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<div className="flex items-center gap-3 mb-2">
<span className="text-3xl">
{pii.severity === 'CRITICAL' ? '🔴' :
pii.severity === 'HIGH' ? '🟠' :
pii.severity === 'MEDIUM' ? '🟡' : '🔵'}
</span>
<div>
<div className="font-mono text-xl font-black text-slate-800">
{pii.column}
</div>
<div className="text-sm text-slate-600 mt-1">
<span className="font-semibold">PII Type:</span> {pii.type.replace(/_/g, ' ')}
{pii.occurrences && (
<>
<span className="mx-2"></span>
<span className="font-semibold">Found in:</span> {pii.occurrences} rows
</>
)}
{pii.confidence && (
<>
<span className="mx-2"></span>
<span className="font-semibold">Confidence:</span> {(pii.confidence * 100).toFixed(0)}%
</>
)}
</div>
</div>
</div>
</div>
<span className={`px-4 py-2 rounded-full text-xs font-black shadow-lg ${
pii.severity === 'CRITICAL' ? 'bg-red-600 text-white' :
pii.severity === 'HIGH' ? 'bg-orange-600 text-white' :
pii.severity === 'MEDIUM' ? 'bg-yellow-600 text-white' :
'bg-blue-600 text-white'
}`}>
{pii.severity} RISK
</span>
</div>
{/* Why is this risky? */}
<div className="mb-4 p-4 bg-white rounded-lg border-2 border-slate-200">
<div className="flex items-start gap-2 mb-2">
<span className="text-xl"></span>
<div className="flex-1">
<div className="text-sm font-black text-slate-700 mb-2">WHY IS THIS FEATURE RISKY?</div>
<p className="text-sm text-slate-700 leading-relaxed">{riskInfo.why}</p>
</div>
</div>
</div>
{/* Impact */}
<div className="mb-4 p-4 bg-gradient-to-r from-red-50 to-orange-50 rounded-lg border-2 border-red-200">
<div className="flex items-start gap-2 mb-2">
<span className="text-xl"></span>
<div className="flex-1">
<div className="text-sm font-black text-red-800 mb-2">POTENTIAL IMPACT IF EXPOSED</div>
<p className="text-sm text-slate-800 leading-relaxed font-semibold">{riskInfo.impact}</p>
</div>
</div>
</div>
{/* GDPR Articles Violated */}
<div className="mb-4 p-4 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg border-2 border-blue-200">
<div className="flex items-start gap-2 mb-2">
<span className="text-xl"></span>
<div className="flex-1">
<div className="text-sm font-black text-blue-800 mb-2">GDPR ARTICLES VIOLATED / APPLICABLE</div>
<div className="space-y-1">
{riskInfo.gdprArticles.map((article, i) => (
<div key={i} className="flex items-start gap-2">
<span className="text-blue-600 mt-1"></span>
<span className="text-sm text-slate-800 font-semibold">{article}</span>
</div>
))}
</div>
</div>
</div>
</div>
{/* Recommended Actions */}
<div className="p-4 bg-gradient-to-r from-green-50 to-emerald-50 rounded-lg border-2 border-green-300">
<div className="flex items-start gap-2 mb-3">
<span className="text-xl"></span>
<div className="flex-1">
<div className="text-sm font-black text-green-800 mb-2">RECOMMENDED ACTIONS TO REDUCE RISK</div>
<ul className="space-y-2">
{riskInfo.actions.map((action, i) => (
<li key={i} className="flex items-start gap-2">
<span className="text-green-600 font-bold mt-0.5">{i + 1}.</span>
<span className="text-sm text-slate-800 font-medium">{action}</span>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
);
})}
</div>
</div>
) : (
<div className="text-sm text-slate-600 bg-green-50 border border-green-200 rounded-lg p-3">
No PII detected in the dataset
<div className="text-sm text-slate-600 bg-green-50 border border-green-200 rounded-lg p-4 flex items-center gap-3">
<span className="text-2xl"></span>
<div>
<div className="font-semibold text-green-800">No PII Detected</div>
<div className="text-xs text-slate-600 mt-1">Dataset appears to be free of personally identifiable information</div>
</div>
</div>
)}
</div>
)}
{/* Violations Section with Enhanced Design */}
)} {/* Violations Section with Enhanced Design */}
{analyzeResult.risk_assessment.violations &&
analyzeResult.risk_assessment.violations.length > 0 && (
<div className="bg-gradient-to-br from-red-50 via-white to-orange-50 rounded-xl border-2 border-red-200 p-6 shadow-lg">
@@ -1074,54 +1572,242 @@ export function CenterPanel({ tab, onAnalyze }: CenterPanelProps) {
</div>
)}
{/* Compliance Status */}
{/* Compliance Status - Enhanced with GDPR Article Details */}
{analyzeResult.risk_assessment.compliance_risks && (
<div className="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-sm">
<div className="flex items-center gap-2 mb-4">
<div className="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-lg">
<div className="flex items-center gap-2 mb-6">
<span className="text-2xl">📋</span>
<h3 className="text-lg font-bold text-slate-800">Compliance Status</h3>
<h3 className="text-lg font-bold text-slate-800">Regulatory Compliance Status</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-4">
{Object.entries(analyzeResult.risk_assessment.compliance_risks)
.filter(([key]) => ['gdpr', 'ccpa', 'hipaa', 'ecoa'].includes(key))
.map(([regulation, data]: [string, any]) => {
if (!data || typeof data !== 'object') return null;
const regulationInfo: Record<string, { name: string; description: string; keyArticles: string[] }> = {
gdpr: {
name: 'GDPR (General Data Protection Regulation)',
description: 'EU regulation protecting personal data and privacy',
keyArticles: [
'Article 5 - Principles (lawfulness, fairness, transparency, purpose limitation, data minimization)',
'Article 6 - Lawful basis for processing',
'Article 7 - Conditions for consent',
'Article 9 - Processing special categories of personal data',
'Article 15-22 - Data subject rights (access, rectification, erasure, portability)',
'Article 25 - Data protection by design and by default',
'Article 32 - Security of processing',
'Article 35 - Data protection impact assessment'
]
},
ccpa: {
name: 'CCPA (California Consumer Privacy Act)',
description: 'California law providing privacy rights to consumers',
keyArticles: [
'Right to Know what personal information is collected',
'Right to Delete personal information',
'Right to Opt-Out of sale of personal information',
'Right to Non-Discrimination for exercising CCPA rights',
'Notice at Collection requirements'
]
},
hipaa: {
name: 'HIPAA (Health Insurance Portability and Accountability Act)',
description: 'US regulation protecting health information',
keyArticles: [
'Privacy Rule - Protected Health Information (PHI) safeguards',
'Security Rule - Administrative, physical, technical safeguards',
'Breach Notification Rule - Incident reporting requirements',
'Minimum Necessary Standard - Access limitation'
]
},
ecoa: {
name: 'ECOA (Equal Credit Opportunity Act)',
description: 'US law prohibiting discrimination in credit decisions',
keyArticles: [
'Prohibition of discrimination based on protected characteristics',
'Adverse action notice requirements',
'Record retention requirements',
'Monitoring and reporting obligations'
]
}
};
const info = regulationInfo[regulation] || { name: regulation.toUpperCase(), description: '', keyArticles: [] };
return (
<div key={regulation} className={`p-4 rounded-lg border-2 ${
data.status === 'COMPLIANT' ? 'bg-green-50 border-green-200' :
data.status === 'PARTIAL' ? 'bg-yellow-50 border-yellow-200' :
data.status === 'NOT_APPLICABLE' ? 'bg-slate-50 border-slate-200' :
'bg-red-50 border-red-200'
<div key={regulation} className={`rounded-xl border-2 overflow-hidden ${
data.status === 'COMPLIANT' ? 'border-green-300 bg-gradient-to-br from-green-50 to-emerald-50' :
data.status === 'PARTIAL' ? 'border-yellow-300 bg-gradient-to-br from-yellow-50 to-orange-50' :
data.status === 'NOT_APPLICABLE' ? 'border-slate-300 bg-gradient-to-br from-slate-50 to-slate-100' :
'border-red-300 bg-gradient-to-br from-red-50 to-rose-50'
}`}>
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-bold text-slate-800 uppercase">
{regulation}
</span>
<span className={`text-xs font-bold px-2 py-1 rounded ${
data.status === 'COMPLIANT' ? 'bg-green-100 text-green-700' :
data.status === 'PARTIAL' ? 'bg-yellow-100 text-yellow-700' :
data.status === 'NOT_APPLICABLE' ? 'bg-slate-100 text-slate-700' :
'bg-red-100 text-red-700'
{/* Header */}
<div className={`p-4 border-b-2 ${
data.status === 'COMPLIANT' ? 'bg-green-100 border-green-200' :
data.status === 'PARTIAL' ? 'bg-yellow-100 border-yellow-200' :
data.status === 'NOT_APPLICABLE' ? 'bg-slate-100 border-slate-200' :
'bg-red-100 border-red-200'
}`}>
{data.status}
<div className="flex items-center justify-between">
<div>
<div className="text-sm font-black text-slate-800 uppercase tracking-wide">
{info.name}
</div>
{info.description && (
<div className="text-xs text-slate-600 mt-1">{info.description}</div>
)}
</div>
<span className={`px-4 py-2 rounded-full text-xs font-black shadow-sm ${
data.status === 'COMPLIANT' ? 'bg-green-600 text-white' :
data.status === 'PARTIAL' ? 'bg-yellow-600 text-white' :
data.status === 'NOT_APPLICABLE' ? 'bg-slate-600 text-white' :
'bg-red-600 text-white'
}`}>
{data.status === 'NOT_APPLICABLE' ? 'N/A' : data.status}
</span>
</div>
</div>
{/* Content */}
<div className="p-4">
{data.applicable === false ? (
<div className="text-sm text-slate-600 italic">
This regulation does not appear to apply to your dataset based on detected data types.
</div>
) : (
<div className="space-y-3">
{/* Score */}
{data.score !== undefined && (
<div className="text-xs text-slate-600 mb-2">
Compliance Score: {(data.score * 100).toFixed(0)}%
<div className="flex items-center gap-3">
<div className="text-xs font-semibold text-slate-600">Compliance Score:</div>
<div className="flex-1 h-3 bg-slate-200 rounded-full overflow-hidden">
<div
className={`h-full transition-all ${
data.score > 0.7 ? 'bg-green-500' :
data.score > 0.4 ? 'bg-yellow-500' :
'bg-red-500'
}`}
style={{ width: `${data.score * 100}%` }}
></div>
</div>
<div className="text-sm font-bold text-slate-800">
{(data.score * 100).toFixed(0)}%
</div>
</div>
)}
{data.applicable === false && (
<div className="text-xs text-slate-600">
Not applicable to this dataset
{/* Compliant Checks */}
{data.compliant_checks && data.compliant_checks.length > 0 && (
<div>
<div className="text-xs font-semibold text-green-700 mb-2"> Compliant Areas:</div>
<div className="flex flex-wrap gap-2">
{data.compliant_checks.map((check: string, idx: number) => (
<span key={idx} className="px-2 py-1 bg-green-100 text-green-800 text-xs rounded border border-green-200">
{check.replace(/_/g, ' ')}
</span>
))}
</div>
</div>
)}
{/* Non-Compliant Checks */}
{data.non_compliant_checks && data.non_compliant_checks.length > 0 && (
<div>
<div className="text-xs font-semibold text-red-700 mb-2"> Non-Compliant Areas:</div>
<div className="flex flex-wrap gap-2">
{data.non_compliant_checks.map((check: string, idx: number) => (
<span key={idx} className="px-2 py-1 bg-red-100 text-red-800 text-xs rounded border border-red-200">
{check.replace(/_/g, ' ')}
</span>
))}
</div>
</div>
)}
{/* Key Articles/Requirements */}
{info.keyArticles.length > 0 && (
<details className="mt-3">
<summary className="text-xs font-semibold text-blue-700 cursor-pointer hover:text-blue-900">
📖 View Key Requirements & Articles
</summary>
<div className="mt-2 pl-4 space-y-2">
{info.keyArticles.map((article, idx) => (
<div key={idx} className="flex items-start gap-2">
<span className="text-blue-600 text-xs mt-0.5"></span>
<span className="text-xs text-slate-700">{article}</span>
</div>
))}
</div>
</details>
)}
{/* Bias Score for ECOA */}
{regulation === 'ecoa' && data.bias_score !== undefined && (
<div className="mt-3 p-3 bg-white rounded border border-slate-200">
<div className="text-xs font-semibold text-slate-600 mb-1">Bias Score (Discrimination Risk):</div>
<div className="flex items-center gap-3">
<div className="flex-1 h-3 bg-slate-200 rounded-full overflow-hidden">
<div
className={`h-full transition-all ${
data.bias_score < 0.3 ? 'bg-green-500' :
data.bias_score < 0.5 ? 'bg-yellow-500' :
'bg-red-500'
}`}
style={{ width: `${data.bias_score * 100}%` }}
></div>
</div>
<div className={`text-sm font-bold ${
data.bias_score < 0.3 ? 'text-green-600' :
data.bias_score < 0.5 ? 'text-yellow-600' :
'text-red-600'
}`}>
{(data.bias_score * 100).toFixed(1)}%
</div>
</div>
<div className="text-xs text-slate-600 mt-1">
{data.bias_score < 0.3 ? 'Low discrimination risk' :
data.bias_score < 0.5 ? 'Moderate discrimination risk - monitor closely' :
'High discrimination risk - immediate remediation required'}
</div>
</div>
)}
</div>
)}
</div>
</div>
);
})}
</div>
{/* Compliance Recommendations */}
{analyzeResult.risk_assessment.compliance_risks.recommendations &&
analyzeResult.risk_assessment.compliance_risks.recommendations.length > 0 && (
<div className="mt-4 p-4 bg-blue-50 rounded-lg border border-blue-200">
<div className="text-sm font-bold text-blue-900 mb-3">📌 Compliance Recommendations</div>
<div className="space-y-2">
{analyzeResult.risk_assessment.compliance_risks.recommendations.map((rec: any, idx: number) => (
<div key={idx} className="flex items-start gap-3 p-3 bg-white rounded border border-blue-200">
<span className={`px-2 py-0.5 text-xs font-bold rounded ${
rec.priority === 'CRITICAL' ? 'bg-red-600 text-white' :
rec.priority === 'HIGH' ? 'bg-orange-600 text-white' :
rec.priority === 'MEDIUM' ? 'bg-yellow-600 text-white' :
'bg-blue-600 text-white'
}`}>
{rec.priority}
</span>
<div className="flex-1">
<div className="text-sm font-semibold text-slate-800">{rec.recommendation}</div>
{rec.rationale && (
<div className="text-xs text-slate-600 mt-1">{rec.rationale}</div>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</div>