Files
intelligence-terminal/lib/security/security-alert-policy.mjs
MrSphay 0c7ddc53b4
All checks were successful
Codex Template Compliance / template-compliance (pull_request) Successful in 7s
Build / test-and-image (pull_request) Successful in 52s
feat: add privacy-aware security manager onboarding
2026-07-05 21:39:55 +02:00

47 lines
1.9 KiB
JavaScript

export function evaluateSecurityAlertPolicy(result, profile, now = new Date()) {
if (!result?.notify) return { send: false, reason: 'agent_declined' };
if (!profile) return { send: true, reason: 'no_profile' };
const priority = ['routine', 'priority', 'flash'].includes(result.priority) ? result.priority : 'routine';
const preference = profile.alertPreference || 'important';
if (preference === 'critical_only' && priority !== 'flash') {
return { send: false, reason: 'critical_only' };
}
if (preference === 'important' && priority === 'routine') {
return { send: false, reason: 'routine_suppressed' };
}
if (priority !== 'flash' && isWithinQuietHours(profile.quietHours, profile.timezone, now)) {
return { send: false, reason: 'quiet_hours' };
}
return { send: true, reason: 'allowed' };
}
export function isWithinQuietHours(value, timezone, now = new Date()) {
const match = String(value || '').match(/^([01]\d|2[0-3]):([0-5]\d)-([01]\d|2[0-3]):([0-5]\d)$/);
if (!match) return false;
const localMinutes = minutesInTimezone(now, timezone);
if (localMinutes == null) return false;
const start = Number(match[1]) * 60 + Number(match[2]);
const end = Number(match[3]) * 60 + Number(match[4]);
if (start === end) return true;
return start < end
? localMinutes >= start && localMinutes < end
: localMinutes >= start || localMinutes < end;
}
function minutesInTimezone(date, timezone) {
try {
const parts = new Intl.DateTimeFormat('en-GB', {
timeZone: timezone || 'UTC',
hour: '2-digit',
minute: '2-digit',
hourCycle: 'h23',
}).formatToParts(date);
const hour = Number(parts.find(part => part.type === 'hour')?.value);
const minute = Number(parts.find(part => part.type === 'minute')?.value);
return Number.isFinite(hour) && Number.isFinite(minute) ? hour * 60 + minute : null;
} catch {
return null;
}
}