// evaluation-soc2-engine.jsx — Verigo Global: SOC 2 readiness evaluation engine
// Questions, scoring, quiz + results components, and a results-PDF generator.
// Common Criteria are assessed across the CC1–CC9 series, then each optional category.
// Exposes window.EVAL_SOC2
const { V: GV, MAXW: GMW, FONT: GFT } = window;
/* ── QUESTION BANK — Common Criteria (CC1–CC9) + optional categories ─── */
// Each question is [criterion code, statement] so every answer maps to a specific SOC 2 criterion.
const SQUESTIONS = [
{ group: 'Security · Common Criteria', theme: 'CC1–CC3 · Governance, Risk & Communication', icon: 'briefcase', controls: 12,
docs: ['Information Security Policy', 'Risk Assessment & Management Policy', 'Human Resources Security Policy'],
q: [
['CC1.1', 'Management has defined and communicated integrity and ethical values, with a code of conduct staff acknowledge.'],
['CC1.3', 'Organizational structures, reporting lines, and security roles & authorities are formally defined.'],
['CC2.2', 'Security objectives and responsibilities are communicated internally to those who need them.'],
['CC3.2', 'A documented risk assessment identifies, analyzes, and rates risks to in-scope systems.'],
] },
{ group: 'Security · Common Criteria', theme: 'CC4–CC5 · Monitoring & Control Activities', icon: 'activity', controls: 5,
docs: ['Logging & Monitoring Policy', 'Control Owner Review Procedure'],
q: [
['CC4.1', 'Controls are monitored through a mix of ongoing and periodic evaluations.'],
['CC4.2', 'Control deficiencies are tracked to remediation and communicated to management.'],
['CC5.2', 'General IT controls (baseline configurations, segregation of duties) are selected and deployed.'],
] },
{ group: 'Security · Common Criteria', theme: 'CC6 · Logical & Physical Access', icon: 'lock', controls: 8,
docs: ['Access Control Policy', 'Access Provisioning & Deprovisioning Procedure', 'Physical & Environmental Security Policy'],
q: [
['CC6.1', 'Logical access is protected by an identity provider, MFA, and least-privilege entitlements.'],
['CC6.2', 'New user access is registered and authorized before it is granted.'],
['CC6.3', 'Access rights are reviewed and recertified on a defined cadence (e.g., quarterly).'],
['CC6.4', 'Physical access to facilities and data environments is restricted and logged.'],
] },
{ group: 'Security · Common Criteria', theme: 'CC7 · System Operations', icon: 'refresh', controls: 5,
docs: ['Vulnerability Management Policy', 'Logging & Monitoring Procedure', 'Incident Response Procedure'],
q: [
['CC7.1', 'Vulnerabilities and configuration changes are detected through scanning and monitoring.'],
['CC7.2', 'System components are monitored for anomalies and security events.'],
['CC7.4', 'Security events are evaluated and incidents are responded to on a documented, exercised process.'],
] },
{ group: 'Security · Common Criteria', theme: 'CC8–CC9 · Change Management & Risk Mitigation', icon: 'layers', controls: 3,
docs: ['Change Management Policy', 'Business Continuity & Disaster Recovery Policy', 'Vendor & Third-Party Management Policy'],
q: [
['CC8.1', 'Changes to infrastructure and software are authorized, tested, and approved before release.'],
['CC9.1', 'Business-disruption risks are mitigated through continuity and recovery planning.'],
['CC9.2', 'Vendor and subservice-organization risk is assessed and monitored.'],
] },
{ group: 'Optional category', theme: 'Availability', icon: 'gauge', controls: 3,
docs: ['Business Continuity & Disaster Recovery Policy', 'Backup Policy'],
q: [
['A1.1', 'System capacity is monitored and managed against processing demand.'],
['A1.2', 'Backups are performed, encrypted, and supported by recovery infrastructure.'],
['A1.3', 'Disaster recovery plans are tested at least annually.'],
] },
{ group: 'Optional category', theme: 'Confidentiality', icon: 'shield', controls: 2,
docs: ['Data Classification & Handling Policy', 'Encryption & Key Management Policy'],
q: [
['C1.1', 'Confidential information is identified, classified, and protected across its lifecycle.'],
['C1.2', 'Confidential information is securely disposed of when no longer required.'],
] },
{ group: 'Optional category', theme: 'Processing Integrity', icon: 'check', controls: 5,
docs: ['Change Management Policy', 'Secure Software Development Policy'],
q: [
['PI1.2', 'System inputs are validated for completeness and accuracy.'],
['PI1.3', 'Processing is monitored to be complete, valid, accurate, and timely.'],
['PI1.4', 'System outputs are reviewed and reconciled for accuracy.'],
] },
{ group: 'Optional category', theme: 'Privacy', icon: 'users', controls: 18,
docs: ['Privacy Policy', 'Data Retention & Disposal Policy'],
q: [
['P1.1', 'A privacy notice describes how personal information is collected and used.'],
['P2.1', 'Choice and consent are obtained before collecting personal information.'],
['P4.3', 'Personal information is retained only as long as needed and disposed of securely.'],
['P5.1', 'Data-subject access and correction requests are handled on a defined process.'],
] },
];
const SOPTIONS = [
['Not started', 0],
['Partial', 1],
['Largely', 2],
['Fully', 3],
];
const SBANDS = [
[0, 'Initial', GV.orange, 'Foundations are largely missing — start with the core policy and risk set.'],
[40, 'Developing', GV.orange, 'Key pieces exist, but real gaps remain before an examination is viable.'],
[60, 'Established', GV.purple, 'A working control environment is in place — focus on closing the weaker areas.'],
[80, 'Optimized', GV.purple, 'Strong posture — fine-tune evidence and keep it continuous.'],
];
const sBandFor = (pct) => { let b = SBANDS[0]; SBANDS.forEach((x) => { if (pct >= x[0]) b = x; }); return b; };
// Sections in scope: Common Criteria are always included; optional categories only if selected.
function sSectionsInScope(criteria) {
return SQUESTIONS.filter((s) => s.group === 'Security · Common Criteria' || !criteria || criteria.indexOf(s.theme) !== -1);
}
function sCompute(answers, sections) {
const secs = sections || SQUESTIONS;
const themes = secs.map((t, ti) => {
const max = t.q.length * 3;
let sum = 0;
t.q.forEach((_, qi) => { sum += (answers[ti + '-' + qi] || 0); });
const pct = Math.round((sum / max) * 100);
return { theme: t.theme, group: t.group, icon: t.icon, docs: t.docs, controls: t.controls, pct, gaps: Math.round((1 - pct / 100) * t.controls) };
});
const totSum = themes.reduce((a, t) => a + (t.pct), 0);
const overall = themes.length ? Math.round(totSum / themes.length) : 0;
const gaps = themes.reduce((a, t) => a + t.gaps, 0);
const totalControls = secs.reduce((a, t) => a + t.controls, 0);
return { themes, overall, gaps, totalControls, band: sBandFor(overall) };
}
/* ── SEGMENTED MATURITY CONTROL ──────────────────────────── */
const SSegmented = ({ value, onChange }) => (
{SOPTIONS.map(([label, val]) => {
const on = value === val;
return (
);
})}
{overall >= 80 ? 'You\u2019re close to examination-ready.' : overall >= 60 ? 'A solid base, with clear gaps to close.' : 'There\u2019s real groundwork to do first.'}
{bandDesc} We estimate ~{gaps} of {results.totalControls} criteria need attention before your examination.
{user && user.company ? ` Prepared for ${user.company}.` : ''}