import React, { useState, useEffect, useRef } from 'react';
import { Shield, FileText, User, Lock, AlertTriangle, CheckCircle, XCircle, Info, ChevronRight, Eye, Edit3, Terminal } from 'lucide-react';
// --- Constants & Config ---
const SECURITY_LEVELS = {
TOP_SECRET: { value: 3, label: "Top Secret", color: "text-red-600", bg: "bg-red-100", border: "border-red-500", badge: "bg-red-600" },
SECRET: { value: 2, label: "Secret", color: "text-orange-600", bg: "bg-orange-100", border: "border-orange-500", badge: "bg-orange-500" },
CONFIDENTIAL: { value: 1, label: "Confidential", color: "text-blue-600", bg: "bg-blue-100", border: "border-blue-500", badge: "bg-blue-500" },
UNCLASSIFIED: { value: 0, label: "Unclassified", color: "text-green-600", bg: "bg-green-100", border: "border-green-500", badge: "bg-green-500" },
};
const INITIAL_USERS = [
{ id: 'u1', name: 'General Alice', role: 'Commander', level: 'TOP_SECRET', avatar: '⭐' },
{ id: 'u2', name: 'Agent Bob', role: 'Field Agent', level: 'SECRET', avatar: '🕵️' },
{ id: 'u3', name: 'Analyst Charlie', role: 'Data Entry', level: 'CONFIDENTIAL', avatar: '👓' },
{ id: 'u4', name: 'Civilian Dave', role: 'Guest', level: 'UNCLASSIFIED', avatar: '😊' },
];
const INITIAL_FILES = [
{ id: 'f1', name: 'Nuclear Launch Codes', content: 'The code is 1234-ALPHA-OMEGA.', level: 'TOP_SECRET' },
{ id: 'f2', name: 'Alien Contact Protocol', content: 'In case of contact, play jazz music.', level: 'TOP_SECRET' },
{ id: 'f3', name: 'Troop Locations', content: 'Troops are moving to sector 7G.', level: 'SECRET' },
{ id: 'f4', name: 'Spy Network List', content: 'Agent X is actually a double agent.', level: 'SECRET' },
{ id: 'f5', name: 'Staff Meeting Minutes', content: 'We need more coffee in the breakroom.', level: 'CONFIDENTIAL' },
{ id: 'f6', name: 'Cafeteria Menu', content: 'Today\'s special: Mystery Meat.', level: 'UNCLASSIFIED' },
];
// --- Helper Components ---
const Badge = ({ level }) => {
const config = SECURITY_LEVELS[level];
return (
{config.label}
);
};
const Modal = ({ isOpen, onClose, title, children, type = 'info' }) => {
if (!isOpen) return null;
const typeStyles = {
success: 'border-green-500 bg-green-50',
error: 'border-red-500 bg-red-50',
info: 'border-blue-500 bg-white'
};
return (
{type === 'success' && }
{type === 'error' && }
{title}
{children}
Close
);
};
// --- Main Application ---
export default function BellLaPadulaSim() {
const [currentUser, setCurrentUser] = useState(INITIAL_USERS[0]);
const [files, setFiles] = useState(INITIAL_FILES);
const [logs, setLogs] = useState([]);
const [modalState, setModalState] = useState({ isOpen: false, title: '', content: '', type: 'info' });
const [showRules, setShowRules] = useState(false);
const logEndRef = useRef(null);
// Auto-scroll logs
useEffect(() => {
if (logEndRef.current) {
logEndRef.current.scrollIntoView({ behavior: 'smooth' });
}
}, [logs]);
const addLog = (action, subject, object, success, reason) => {
const timestamp = new Date().toLocaleTimeString();
setLogs(prev => [...prev, { id: Date.now(), timestamp, action, subject, object, success, reason }]);
};
const checkAccess = (userLevel, fileLevel, action) => {
const userVal = SECURITY_LEVELS[userLevel].value;
const fileVal = SECURITY_LEVELS[fileLevel].value;
if (action === 'READ') {
// Simple Security Property: No Read Up
if (userVal >= fileVal) return { allowed: true };
return { allowed: false, reason: 'No Read Up violation: Subject clearance is lower than Object classification.' };
}
if (action === 'WRITE') {
// *-Property (Star Property): No Write Down
// Strictly speaking, BLP allows write up (blind write), but forbids write down.
if (userVal <= fileVal) return { allowed: true };
return { allowed: false, reason: '*-Property violation: Subject cannot write to lower classification (potential leak).' };
}
return { allowed: false, reason: 'Unknown action' };
};
const handleRead = (file) => {
const result = checkAccess(currentUser.level, file.level, 'READ');
if (result.allowed) {
setModalState({
isOpen: true,
title: 'Access Granted',
type: 'success',
content: (
Reading File: {file.name}
{file.content}
Rule Applied: Simple Security Property (Subject Level ≥ Object Level)
)
});
addLog('READ', currentUser, file, true, 'Access Granted');
} else {
setModalState({
isOpen: true,
title: 'Access Denied',
type: 'error',
content: (
Cannot Read File: {file.name}
{result.reason}
CONFIDENTIALITY GUARD: BLP prevents you from reading data above your clearance level.
)
});
addLog('READ', currentUser, file, false, result.reason);
}
};
const handleWrite = (file) => {
const result = checkAccess(currentUser.level, file.level, 'WRITE');
if (result.allowed) {
setModalState({
isOpen: true,
title: 'Write Operation Allowed',
type: 'success',
content: (
Writing to: {file.name}
You appended new data to this secure file.
Rule Applied: *-Property (Subject Level ≤ Object Level). Writing up is allowed to preserve confidentiality of the subject's high-level knowledge (blind write).
)
});
addLog('WRITE', currentUser, file, true, 'Access Granted');
} else {
setModalState({
isOpen: true,
title: 'Write Operation Blocked',
type: 'error',
content: (
Cannot Write to: {file.name}
{result.reason}
LEAK PREVENTION: You hold a higher clearance. Writing to a lower level could accidentally leak secrets you know.
)
});
addLog('WRITE', currentUser, file, false, result.reason);
}
};
return (
{/* Header */}
Bell-LaPadula Simulator
CONFIDENTIALITY MODEL // DoD STANDARD
setShowRules(!showRules)}
className="flex items-center gap-2 text-sm bg-slate-800 hover:bg-slate-700 px-3 py-2 rounded-lg transition-colors border border-slate-700"
>
{showRules ? 'Hide Rules' : 'Show Rules'}
{/* Rules Banner */}
{showRules && (
Simple Security Property (No Read Up)
A subject at a specific clearance level cannot read an object at a higher classification level.
Logic: Clearance ≥ Classification
*-Property (No Write Down)
A subject cannot write information to an object at a lower classification level. This prevents high-level secrets from being copied to low-level documents.
Logic: Clearance ≤ Classification
)}
{/* Left Column: User Selection & Status */}
Select Subject
{INITIAL_USERS.map(user => (
setCurrentUser(user)}
className={`w-full text-left px-4 py-3 flex items-center gap-3 transition-colors ${
currentUser.id === user.id ? 'bg-blue-50 border-l-4 border-blue-500' : 'hover:bg-slate-50 border-l-4 border-transparent'
}`}
>
{user.avatar}
))}
Current Clearance
{currentUser.avatar}
{currentUser.name}
You are acting as this subject for all operations.
{/* Center Column: Files Grid */}
Files (Objects)
System: SECURE
{files.map(file => {
const levelConfig = SECURITY_LEVELS[file.level];
return (
{file.name}
ID: {file.id.toUpperCase()}
handleRead(file)}
className="flex items-center justify-center gap-2 px-3 py-2 bg-white border border-slate-300 rounded hover:bg-blue-50 hover:text-blue-600 hover:border-blue-300 transition-colors text-sm font-medium"
>
Read
handleWrite(file)}
className="flex items-center justify-center gap-2 px-3 py-2 bg-white border border-slate-300 rounded hover:bg-orange-50 hover:text-orange-600 hover:border-orange-300 transition-colors text-sm font-medium"
>
Write
);
})}
{/* Right Column: System Log */}
{logs.length === 0 && (
-- No activity recorded --
)}
{logs.map(log => (
{log.timestamp}
{log.success ? 'ALLOWED' : 'DENIED'}
{log.subject.name} attempted to {log.action} {log.object.name}
{!log.success && (
Error: {log.reason}
)}
))}
setModalState(prev => ({ ...prev, isOpen: false }))}
title={modalState.title}
type={modalState.type}
>
{modalState.content}
);
}