@@ -5,6 +5,10 @@ import {
55 PCIDSSConfigSchema ,
66 AuditLogConfigSchema ,
77 ComplianceConfigSchema ,
8+ AuditFindingSeveritySchema ,
9+ AuditFindingStatusSchema ,
10+ AuditFindingSchema ,
11+ AuditScheduleSchema ,
812} from './compliance.zod' ;
913
1014describe ( 'GDPRConfigSchema' , ( ) => {
@@ -226,4 +230,178 @@ describe('ComplianceConfigSchema', () => {
226230 it ( 'should reject missing auditLog' , ( ) => {
227231 expect ( ( ) => ComplianceConfigSchema . parse ( { } ) ) . toThrow ( ) ;
228232 } ) ;
233+
234+ it ( 'should accept configuration with audit schedules' , ( ) => {
235+ const config = ComplianceConfigSchema . parse ( {
236+ auditLog : {
237+ events : [ 'create' , 'update' ] ,
238+ } ,
239+ auditSchedules : [
240+ {
241+ id : 'AUDIT-2024-Q1' ,
242+ title : 'Q1 ISO 27001 Internal Audit' ,
243+ scope : [ 'access_control' , 'encryption' ] ,
244+ framework : 'iso27001' ,
245+ scheduledAt : 1711929600000 ,
246+ assessor : 'internal_audit_team' ,
247+ } ,
248+ ] ,
249+ } ) ;
250+
251+ expect ( config . auditSchedules ) . toHaveLength ( 1 ) ;
252+ expect ( config . auditSchedules ! [ 0 ] . framework ) . toBe ( 'iso27001' ) ;
253+ } ) ;
254+ } ) ;
255+
256+ describe ( 'AuditFindingSeveritySchema' , ( ) => {
257+ it ( 'should accept all valid severities' , ( ) => {
258+ const severities = [ 'critical' , 'major' , 'minor' , 'observation' ] ;
259+
260+ severities . forEach ( ( severity ) => {
261+ expect ( ( ) => AuditFindingSeveritySchema . parse ( severity ) ) . not . toThrow ( ) ;
262+ } ) ;
263+ } ) ;
264+
265+ it ( 'should reject invalid severity' , ( ) => {
266+ expect ( ( ) => AuditFindingSeveritySchema . parse ( 'warning' ) ) . toThrow ( ) ;
267+ } ) ;
268+ } ) ;
269+
270+ describe ( 'AuditFindingStatusSchema' , ( ) => {
271+ it ( 'should accept all valid statuses' , ( ) => {
272+ const statuses = [ 'open' , 'in_remediation' , 'remediated' , 'verified' , 'accepted_risk' , 'closed' ] ;
273+
274+ statuses . forEach ( ( status ) => {
275+ expect ( ( ) => AuditFindingStatusSchema . parse ( status ) ) . not . toThrow ( ) ;
276+ } ) ;
277+ } ) ;
278+
279+ it ( 'should reject invalid status' , ( ) => {
280+ expect ( ( ) => AuditFindingStatusSchema . parse ( 'pending' ) ) . toThrow ( ) ;
281+ } ) ;
282+ } ) ;
283+
284+ describe ( 'AuditFindingSchema' , ( ) => {
285+ it ( 'should accept valid finding' , ( ) => {
286+ const finding = AuditFindingSchema . parse ( {
287+ id : 'FIND-2024-001' ,
288+ title : 'Insufficient access logging' ,
289+ description : 'PHI access events are not being logged for HIPAA compliance' ,
290+ severity : 'major' ,
291+ status : 'in_remediation' ,
292+ controlReference : 'A.8.15' ,
293+ framework : 'iso27001' ,
294+ identifiedAt : 1704067200000 ,
295+ identifiedBy : 'external_auditor' ,
296+ remediationPlan : 'Implement audit logging for all PHI access events' ,
297+ remediationDeadline : 1706745600000 ,
298+ } ) ;
299+
300+ expect ( finding . severity ) . toBe ( 'major' ) ;
301+ expect ( finding . framework ) . toBe ( 'iso27001' ) ;
302+ } ) ;
303+
304+ it ( 'should accept minimal finding' , ( ) => {
305+ const finding = AuditFindingSchema . parse ( {
306+ id : 'FIND-2024-002' ,
307+ title : 'Missing encryption' ,
308+ description : 'Field-level encryption not enabled' ,
309+ severity : 'minor' ,
310+ status : 'open' ,
311+ identifiedAt : Date . now ( ) ,
312+ identifiedBy : 'internal_audit' ,
313+ } ) ;
314+
315+ expect ( finding . controlReference ) . toBeUndefined ( ) ;
316+ expect ( finding . remediationPlan ) . toBeUndefined ( ) ;
317+ } ) ;
318+
319+ it ( 'should accept verified finding' , ( ) => {
320+ const finding = AuditFindingSchema . parse ( {
321+ id : 'FIND-2024-003' ,
322+ title : 'Weak password policy' ,
323+ description : 'Password minimum length below 12 characters' ,
324+ severity : 'observation' ,
325+ status : 'verified' ,
326+ identifiedAt : 1704067200000 ,
327+ identifiedBy : 'auditor' ,
328+ verifiedAt : 1706745600000 ,
329+ verifiedBy : 'senior_auditor' ,
330+ notes : 'Password policy updated and verified' ,
331+ } ) ;
332+
333+ expect ( finding . verifiedAt ) . toBe ( 1706745600000 ) ;
334+ expect ( finding . verifiedBy ) . toBe ( 'senior_auditor' ) ;
335+ } ) ;
336+
337+ it ( 'should reject missing required fields' , ( ) => {
338+ expect ( ( ) => AuditFindingSchema . parse ( { } ) ) . toThrow ( ) ;
339+ } ) ;
340+ } ) ;
341+
342+ describe ( 'AuditScheduleSchema' , ( ) => {
343+ it ( 'should accept valid schedule with defaults' , ( ) => {
344+ const schedule = AuditScheduleSchema . parse ( {
345+ id : 'AUDIT-2024-Q1' ,
346+ title : 'Q1 ISO 27001 Internal Audit' ,
347+ scope : [ 'access_control' , 'encryption' , 'incident_response' ] ,
348+ framework : 'iso27001' ,
349+ scheduledAt : 1711929600000 ,
350+ assessor : 'internal_audit_team' ,
351+ } ) ;
352+
353+ expect ( schedule . isExternal ) . toBe ( false ) ;
354+ expect ( schedule . recurrenceMonths ) . toBe ( 0 ) ;
355+ expect ( schedule . findings ) . toBeUndefined ( ) ;
356+ } ) ;
357+
358+ it ( 'should accept full schedule with findings' , ( ) => {
359+ const schedule = AuditScheduleSchema . parse ( {
360+ id : 'AUDIT-2024-EXT' ,
361+ title : 'Annual External ISO 27001 Audit' ,
362+ scope : [ 'all_controls' ] ,
363+ framework : 'iso27001' ,
364+ scheduledAt : 1711929600000 ,
365+ completedAt : 1712534400000 ,
366+ assessor : 'External Audit Firm LLC' ,
367+ isExternal : true ,
368+ recurrenceMonths : 12 ,
369+ findings : [
370+ {
371+ id : 'FIND-001' ,
372+ title : 'Missing incident response plan' ,
373+ description : 'No documented incident response procedure' ,
374+ severity : 'major' ,
375+ status : 'open' ,
376+ controlReference : 'A.5.24' ,
377+ framework : 'iso27001' ,
378+ identifiedAt : 1712534400000 ,
379+ identifiedBy : 'External Audit Firm LLC' ,
380+ } ,
381+ ] ,
382+ } ) ;
383+
384+ expect ( schedule . isExternal ) . toBe ( true ) ;
385+ expect ( schedule . recurrenceMonths ) . toBe ( 12 ) ;
386+ expect ( schedule . findings ) . toHaveLength ( 1 ) ;
387+ } ) ;
388+
389+ it ( 'should accept all framework values' , ( ) => {
390+ const frameworks = [ 'gdpr' , 'hipaa' , 'sox' , 'pci_dss' , 'ccpa' , 'iso27001' ] ;
391+
392+ frameworks . forEach ( ( framework ) => {
393+ expect ( ( ) => AuditScheduleSchema . parse ( {
394+ id : `AUDIT-${ framework } ` ,
395+ title : `${ framework } audit` ,
396+ scope : [ 'general' ] ,
397+ framework,
398+ scheduledAt : Date . now ( ) ,
399+ assessor : 'auditor' ,
400+ } ) ) . not . toThrow ( ) ;
401+ } ) ;
402+ } ) ;
403+
404+ it ( 'should reject missing required fields' , ( ) => {
405+ expect ( ( ) => AuditScheduleSchema . parse ( { } ) ) . toThrow ( ) ;
406+ } ) ;
229407} ) ;
0 commit comments