116 lines
3.8 KiB
JavaScript
116 lines
3.8 KiB
JavaScript
// lib/audit.js — Tamper-evident audit log storage
|
|
|
|
import { hashChain, hashEvent } from './hash.js';
|
|
|
|
const MAX_EVENTS = 1000;
|
|
const MAX_VIOLATIONS = 500;
|
|
|
|
export async function addEvent(event) {
|
|
const { auditLog = [] } = await chrome.storage.local.get(['auditLog']);
|
|
auditLog.push(event);
|
|
if (auditLog.length > MAX_EVENTS) {
|
|
auditLog.splice(0, auditLog.length - MAX_EVENTS);
|
|
}
|
|
await chrome.storage.local.set({ auditLog });
|
|
}
|
|
|
|
export async function addViolation(violation) {
|
|
const { violations = [] } = await chrome.storage.local.get(['violations']);
|
|
violations.push(violation);
|
|
if (violations.length > MAX_VIOLATIONS) {
|
|
violations.splice(0, violations.length - MAX_VIOLATIONS);
|
|
}
|
|
await chrome.storage.local.set({ violations });
|
|
}
|
|
|
|
export async function getAuditLog(limit = 100) {
|
|
const { auditLog = [] } = await chrome.storage.local.get(['auditLog']);
|
|
return auditLog.slice(-limit).reverse();
|
|
}
|
|
|
|
export async function getViolations(limit = 100) {
|
|
const { violations = [] } = await chrome.storage.local.get(['violations']);
|
|
return violations.slice(-limit).reverse();
|
|
}
|
|
|
|
export async function getStats() {
|
|
const { auditLog = [], violations = [], activeAgents = {} } = await chrome.storage.local.get([
|
|
'auditLog', 'violations', 'activeAgents'
|
|
]);
|
|
|
|
const totalEvents = auditLog.length;
|
|
const totalViolations = violations.length;
|
|
const activeCount = Object.keys(activeAgents).length;
|
|
|
|
const severityCounts = { info: 0, low: 0, medium: 0, high: 0, critical: 0 };
|
|
for (const v of violations) {
|
|
severityCounts[v.severity] = (severityCounts[v.severity] || 0) + 1;
|
|
}
|
|
|
|
const last24h = Date.now() - 24 * 60 * 60 * 1000;
|
|
const recentEvents = auditLog.filter(e => new Date(e.timestamp).getTime() > last24h).length;
|
|
const recentViolations = violations.filter(v => new Date(v.timestamp).getTime() > last24h).length;
|
|
|
|
const detectorCounts = {};
|
|
for (const v of violations) {
|
|
detectorCounts[v.detector] = (detectorCounts[v.detector] || 0) + 1;
|
|
}
|
|
|
|
const riskScore = Math.min(100, Math.round(
|
|
(severityCounts.critical * 25) +
|
|
(severityCounts.high * 10) +
|
|
(severityCounts.medium * 5) +
|
|
(severityCounts.low * 1) +
|
|
(totalEvents > 0 ? (totalViolations / totalEvents) * 20 : 0)
|
|
));
|
|
|
|
const complianceStatus = riskScore < 20 ? 'compliant' : riskScore < 50 ? 'at-risk' : 'non-compliant';
|
|
|
|
return {
|
|
totalEvents,
|
|
totalViolations,
|
|
activeCount,
|
|
severityCounts,
|
|
recentEvents,
|
|
recentViolations,
|
|
detectorCounts,
|
|
riskScore,
|
|
complianceStatus,
|
|
lastUpdated: new Date().toISOString()
|
|
};
|
|
}
|
|
|
|
export async function exportAuditLog() {
|
|
const { auditLog = [], violations = [] } = await chrome.storage.local.get(['auditLog', 'violations']);
|
|
return {
|
|
exportDate: new Date().toISOString(),
|
|
totalEvents: auditLog.length,
|
|
totalViolations: violations.length,
|
|
events: auditLog,
|
|
violations: violations,
|
|
integrity: hashChain(auditLog)
|
|
};
|
|
}
|
|
|
|
export async function searchAuditLog(query) {
|
|
const { auditLog = [] } = await chrome.storage.local.get(['auditLog']);
|
|
const q = query.toLowerCase();
|
|
return auditLog.filter(e =>
|
|
(e.agent || '').toLowerCase().includes(q) ||
|
|
(e.type || '').toLowerCase().includes(q) ||
|
|
(e.tool || '').toLowerCase().includes(q) ||
|
|
(e.target || '').toLowerCase().includes(q) ||
|
|
(e.url || '').toLowerCase().includes(q)
|
|
).reverse().slice(0, 100);
|
|
}
|
|
|
|
export async function verifyIntegrity() {
|
|
const { auditLog = [] } = await chrome.storage.local.get(['auditLog']);
|
|
if (auditLog.length === 0) return { valid: true, eventsChecked: 0 };
|
|
const expected = hashChain(auditLog);
|
|
const stored = (await chrome.storage.local.get(['auditChainHash'])).auditChainHash;
|
|
const valid = stored === expected;
|
|
await chrome.storage.local.set({ auditChainHash: expected });
|
|
return { valid, eventsChecked: auditLog.length, expected };
|
|
}
|