/** * Controls composable for compliance controls management */ import { computed, type ComputedRef, type Ref, ref } from 'vue' import { useComplianceStore } from '../plugin' import type { Control, Evidence, Risk, ControlDomain, ImplementationStatus, EvidenceType, RiskLikelihood, RiskImpact, } from '@breakpilot/compliance-sdk-types' export interface UseControlsReturn { // Controls controls: ComputedRef controlsByDomain: ComputedRef> implementedControls: ComputedRef pendingControls: ComputedRef getControl: (id: string) => Control | undefined addControl: (control: Omit) => void updateControl: (id: string, updates: Partial) => void deleteControl: (id: string) => void setControlStatus: (id: string, status: ImplementationStatus) => void // Evidence evidence: ComputedRef validEvidence: ComputedRef expiredEvidence: ComputedRef getEvidenceForControl: (controlId: string) => Evidence[] addEvidence: (evidence: Omit) => void updateEvidence: (id: string, updates: Partial) => void deleteEvidence: (id: string) => void // Risks risks: ComputedRef criticalRisks: ComputedRef unmitigatedRisks: ComputedRef getRisksForControl: (controlId: string) => Risk[] addRisk: (risk: Omit) => void updateRisk: (id: string, updates: Partial) => void deleteRisk: (id: string) => void assessRisk: (id: string, likelihood: RiskLikelihood, impact: RiskImpact) => void // Compliance Score complianceScore: ComputedRef scoreByDomain: ComputedRef> } export function useControls(): UseControlsReturn { const store = useComplianceStore() const { state, dispatch, compliance } = store // Controls const controls = computed(() => state.controls) const controlsByDomain = computed(() => { const domains: ControlDomain[] = [ 'ACCESS_CONTROL', 'DATA_PROTECTION', 'NETWORK_SECURITY', 'INCIDENT_RESPONSE', 'BUSINESS_CONTINUITY', 'COMPLIANCE', 'RISK_MANAGEMENT', 'ASSET_MANAGEMENT', 'HUMAN_RESOURCES', ] return domains.reduce( (acc, domain) => { acc[domain] = state.controls.filter(c => c.domain === domain) return acc }, {} as Record ) }) const implementedControls = computed(() => state.controls.filter(c => c.implementationStatus === 'IMPLEMENTED') ) const pendingControls = computed(() => state.controls.filter(c => c.implementationStatus === 'NOT_IMPLEMENTED') ) const getControl = (id: string): Control | undefined => { return state.controls.find(c => c.id === id) } const addControl = (control: Omit): void => { dispatch({ type: 'ADD_CONTROL', payload: control }) } const updateControl = (id: string, updates: Partial): void => { dispatch({ type: 'UPDATE_CONTROL', payload: { id, updates } }) } const deleteControl = (id: string): void => { dispatch({ type: 'DELETE_CONTROL', payload: id }) } const setControlStatus = (id: string, status: ImplementationStatus): void => { dispatch({ type: 'UPDATE_CONTROL', payload: { id, updates: { implementationStatus: status } }, }) } // Evidence const evidence = computed(() => state.evidence) const validEvidence = computed(() => { const now = new Date() return state.evidence.filter(e => !e.validUntil || new Date(e.validUntil) > now) }) const expiredEvidence = computed(() => { const now = new Date() return state.evidence.filter(e => e.validUntil && new Date(e.validUntil) <= now) }) const getEvidenceForControl = (controlId: string): Evidence[] => { return state.evidence.filter(e => e.controlIds.includes(controlId)) } const addEvidence = (ev: Omit): void => { dispatch({ type: 'ADD_EVIDENCE', payload: ev }) } const updateEvidence = (id: string, updates: Partial): void => { dispatch({ type: 'UPDATE_EVIDENCE', payload: { id, updates } }) } const deleteEvidence = (id: string): void => { dispatch({ type: 'DELETE_EVIDENCE', payload: id }) } // Risks const risks = computed(() => state.risks) const criticalRisks = computed(() => compliance.getCriticalRisks()) const unmitigatedRisks = computed(() => state.risks.filter(r => r.status === 'IDENTIFIED' || r.status === 'ANALYZED') ) const getRisksForControl = (controlId: string): Risk[] => { return state.risks.filter(r => r.controlIds?.includes(controlId)) } const addRisk = (risk: Omit): void => { dispatch({ type: 'ADD_RISK', payload: risk }) } const updateRisk = (id: string, updates: Partial): void => { dispatch({ type: 'UPDATE_RISK', payload: { id, updates } }) } const deleteRisk = (id: string): void => { dispatch({ type: 'DELETE_RISK', payload: id }) } const assessRisk = (id: string, likelihood: RiskLikelihood, impact: RiskImpact): void => { const severity = likelihood * impact let severityLevel: Risk['severity'] if (severity >= 20) severityLevel = 'CRITICAL' else if (severity >= 12) severityLevel = 'HIGH' else if (severity >= 6) severityLevel = 'MEDIUM' else severityLevel = 'LOW' dispatch({ type: 'UPDATE_RISK', payload: { id, updates: { likelihood, impact, severity: severityLevel, status: 'ANALYZED', }, }, }) } // Compliance Score const complianceScore = computed(() => { const score = compliance.calculateComplianceScore() return score.overall }) const scoreByDomain = computed(() => { const domains: ControlDomain[] = [ 'ACCESS_CONTROL', 'DATA_PROTECTION', 'NETWORK_SECURITY', 'INCIDENT_RESPONSE', 'BUSINESS_CONTINUITY', 'COMPLIANCE', 'RISK_MANAGEMENT', 'ASSET_MANAGEMENT', 'HUMAN_RESOURCES', ] return domains.reduce( (acc, domain) => { const domainControls = state.controls.filter(c => c.domain === domain) if (domainControls.length === 0) { acc[domain] = 0 return acc } const implemented = domainControls.filter(c => c.implementationStatus === 'IMPLEMENTED') const partial = domainControls.filter(c => c.implementationStatus === 'PARTIAL') acc[domain] = Math.round( ((implemented.length + partial.length * 0.5) / domainControls.length) * 100 ) return acc }, {} as Record ) }) return { controls, controlsByDomain, implementedControls, pendingControls, getControl, addControl, updateControl, deleteControl, setControlStatus, evidence, validEvidence, expiredEvidence, getEvidenceForControl, addEvidence, updateEvidence, deleteEvidence, risks, criticalRisks, unmitigatedRisks, getRisksForControl, addRisk, updateRisk, deleteRisk, assessRisk, complianceScore, scoreByDomain, } }