@grc-claw/compliance-orchestrator 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,509 @@
1
+ import type {
2
+ FrameworkCode,
3
+ RegulationAST,
4
+ ASTControlNode,
5
+ PolicyAST,
6
+ PolicyAtom,
7
+ ControlStatus,
8
+ DriftEvent,
9
+ RiskAssessment,
10
+ ComplianceState,
11
+ } from '../types.js';
12
+
13
+ export interface ReasoningResult {
14
+ control: string;
15
+ decision: 'compliant' | 'non-compliant' | 'partial' | 'unknown';
16
+ confidence: number;
17
+ proof: string[];
18
+ counterExample?: string;
19
+ reasoningPath: string[];
20
+ symbolicProof: SymbolicProof;
21
+ }
22
+
23
+ export interface SymbolicProof {
24
+ obligations: ProofObligation[];
25
+ discharged: string[];
26
+ remaining: string[];
27
+ valid: boolean;
28
+ }
29
+
30
+ export interface ProofObligation {
31
+ id: string;
32
+ formula: string;
33
+ status: 'proven' | 'disproven' | 'unknown' | 'assumed';
34
+ evidenceRef?: string;
35
+ }
36
+
37
+ export interface ReasoningContext {
38
+ orgId: string;
39
+ framework: FrameworkCode;
40
+ currentEvidence: Map<string, EvidenceItem[]>;
41
+ configurationState: ConfigurationState;
42
+ riskTolerance: 'low' | 'medium' | 'high';
43
+ previousState?: ComplianceState;
44
+ }
45
+
46
+ export interface EvidenceItem {
47
+ id: string;
48
+ controlId: string;
49
+ type: string;
50
+ hash: string;
51
+ timestamp: string;
52
+ valid: boolean;
53
+ metadata?: Record<string, unknown>;
54
+ }
55
+
56
+ export interface ConfigurationState {
57
+ iam: IAMState;
58
+ network: NetworkState;
59
+ data: DataState;
60
+ monitoring: MonitoringState;
61
+ physical: PhysicalState;
62
+ }
63
+
64
+ export interface IAMState {
65
+ mfaEnabled: boolean;
66
+ privilegedUsers: string[];
67
+ sessionTimeout: number;
68
+ lastPasswordRotation: string;
69
+ rbacPolicyVersion: string;
70
+ mfaEnforcementRate: number;
71
+ }
72
+
73
+ export interface NetworkState {
74
+ firewallRules: number;
75
+ segmentationEnabled: boolean;
76
+ idsEnabled: boolean;
77
+ tlsVersion: string;
78
+ publicEndpoints: string[];
79
+ }
80
+
81
+ export interface DataState {
82
+ encryptionAtRest: boolean;
83
+ encryptionInTransit: boolean;
84
+ backupEnabled: boolean;
85
+ backupFrequency: string;
86
+ lastBackup: string;
87
+ retentionDays: number;
88
+ }
89
+
90
+ export interface MonitoringState {
91
+ siemEnabled: boolean;
92
+ logRetentionDays: number;
93
+ alertingEnabled: boolean;
94
+ mttr: number;
95
+ monitoringCoverage: number;
96
+ }
97
+
98
+ export interface PhysicalState {
99
+ accessControl: boolean;
100
+ cctvEnabled: boolean;
101
+ environmentalMonitoring: boolean;
102
+ visitorManagement: boolean;
103
+ }
104
+
105
+ interface Z3Variable {
106
+ name: string;
107
+ type: 'bool' | 'int' | 'string';
108
+ value?: unknown;
109
+ }
110
+
111
+ interface Z3Constraint {
112
+ expression: string;
113
+ variables: Z3Variable[];
114
+ }
115
+
116
+ export class NeuroSymbolicReasoner {
117
+ private asts: Map<FrameworkCode, RegulationAST>;
118
+ private constraintCache: Map<string, Z3Constraint[]> = new Map();
119
+
120
+ constructor(asts: Map<FrameworkCode, RegulationAST>) {
121
+ this.asts = asts;
122
+ }
123
+
124
+ async reason(context: ReasoningContext): Promise<ComplianceState> {
125
+ const ast = this.asts.get(context.framework);
126
+ if (!ast) throw new Error(`Framework ${context.framework} not compiled`);
127
+
128
+ const controlStatuses: ControlStatus[] = [];
129
+ const drift: DriftEvent[] = [];
130
+ const risks: RiskAssessment[] = [];
131
+
132
+ for (const control of ast.controls) {
133
+ const result = this.evaluateControl(control, context);
134
+ const evidence = context.currentEvidence.get(control.id) ?? [];
135
+
136
+ controlStatuses.push({
137
+ controlId: control.id,
138
+ status: this.mapDecisionToStatus(result.decision),
139
+ lastVerified: new Date().toISOString(),
140
+ evidenceCount: evidence.length,
141
+ score: result.confidence * 100,
142
+ issues: result.decision === 'non-compliant'
143
+ ? [{
144
+ id: `issue-${control.id}-${Date.now()}`,
145
+ severity: control.severity === 'CRITICAL' ? 'CRITICAL' : 'HIGH',
146
+ description: `Control ${control.code} is non-compliant: ${result.proof.join('; ')}`,
147
+ detectedAt: new Date().toISOString(),
148
+ }]
149
+ : [],
150
+ });
151
+
152
+ const risk = this.assessRisk(control, result, context);
153
+ risks.push(risk);
154
+
155
+ if (context.previousState) {
156
+ const prevStatus = context.previousState.controlStatuses.find((s) => s.controlId === control.id);
157
+ if (prevStatus && prevStatus.status === 'compliant' && result.decision !== 'compliant') {
158
+ drift.push({
159
+ id: `drift-${control.id}-${Date.now()}`,
160
+ controlId: control.id,
161
+ detectedAt: new Date().toISOString(),
162
+ type: 'policy',
163
+ before: prevStatus.status,
164
+ after: result.decision,
165
+ severity: control.severity ?? 'MEDIUM',
166
+ autoRemediated: false,
167
+ });
168
+ }
169
+ }
170
+ }
171
+
172
+ const compliant = controlStatuses.filter((s) => s.status === 'compliant').length;
173
+ const total = controlStatuses.length;
174
+ const overallScore = total > 0 ? (compliant / total) * 100 : 0;
175
+
176
+ return {
177
+ orgId: context.orgId,
178
+ timestamp: new Date().toISOString(),
179
+ framework: context.framework,
180
+ overallScore,
181
+ controlStatuses,
182
+ drift,
183
+ risks,
184
+ };
185
+ }
186
+
187
+ evaluateControl(control: ASTControlNode, context: ReasoningContext): ReasoningResult {
188
+ const proof: string[] = [];
189
+ const reasoningPath: string[] = [];
190
+ const obligations: ProofObligation[] = [];
191
+ const discharged: string[] = [];
192
+ const remaining: string[] = [];
193
+
194
+ reasoningPath.push(`Evaluating control ${control.code}: ${control.title}`);
195
+
196
+ const evidence = context.currentEvidence.get(control.id) ?? [];
197
+ const validEvidence = evidence.filter((e) => e.valid);
198
+
199
+ if (validEvidence.length === 0) {
200
+ proof.push(`No valid evidence found for control ${control.code}`);
201
+ remaining.push(`evidence-${control.id}`);
202
+ return {
203
+ control: control.id,
204
+ decision: 'unknown',
205
+ confidence: 0,
206
+ proof,
207
+ reasoningPath,
208
+ symbolicProof: { obligations: [], discharged: [], remaining, valid: false },
209
+ };
210
+ }
211
+
212
+ reasoningPath.push(`Found ${validEvidence.length} valid evidence items`);
213
+
214
+ let satisfied = true;
215
+ let partiallySatisfied = false;
216
+
217
+ for (const obligation of this.symbolicCheck(control, context)) {
218
+ obligations.push(obligation);
219
+ if (obligation.status === 'proven') {
220
+ discharged.push(obligation.id);
221
+ proof.push(`Obligation ${obligation.id} proven: ${obligation.formula}`);
222
+ } else if (obligation.status === 'disproven') {
223
+ satisfied = false;
224
+ proof.push(`Obligation ${obligation.id} violated: ${obligation.formula}`);
225
+ } else {
226
+ partiallySatisfied = true;
227
+ }
228
+ }
229
+
230
+ const confidence = this.calculateConfidence(control, evidence, obligations, context);
231
+ const decision = satisfied ? 'compliant' : partiallySatisfied ? 'partial' : 'non-compliant';
232
+
233
+ return {
234
+ control: control.id,
235
+ decision,
236
+ confidence,
237
+ proof,
238
+ reasoningPath,
239
+ symbolicProof: { obligations, discharged, remaining, valid: satisfied },
240
+ };
241
+ }
242
+
243
+ private symbolicCheck(control: ASTControlNode, context: ReasoningContext): ProofObligation[] {
244
+ const obligations: ProofObligation[] = [];
245
+ const { configurationState: state } = context;
246
+
247
+ switch (control.code) {
248
+ case 'A.8.2': // Privileged Access Rights
249
+ obligations.push({
250
+ id: 'priv-access-mfa',
251
+ formula: 'all_privileged_users.mfa_enabled = true',
252
+ status: state.iam.mfaEnabled ? 'proven' : 'disproven',
253
+ });
254
+ obligations.push({
255
+ id: 'priv-access-count',
256
+ formula: 'count(privileged_users) <= threshold',
257
+ status: state.iam.privilegedUsers.length <= 10 ? 'proven' : 'disproven',
258
+ });
259
+ obligations.push({
260
+ id: 'priv-access-rotation',
261
+ formula: 'password_age <= 90_days',
262
+ status: this.isPasswordFresh(state.iam.lastPasswordRotation, 90) ? 'proven' : 'disproven',
263
+ });
264
+ break;
265
+
266
+ case 'A.8.5': // Secure Authentication
267
+ obligations.push({
268
+ id: 'auth-mfa',
269
+ formula: 'mfa_enforcement_rate >= 95_percent',
270
+ status: state.iam.mfaEnforcementRate >= 0.95 ? 'proven' : 'disproven',
271
+ });
272
+ obligations.push({
273
+ id: 'auth-session',
274
+ formula: 'session_timeout <= 15_minutes',
275
+ status: state.iam.sessionTimeout <= 900 ? 'proven' : 'disproven',
276
+ });
277
+ break;
278
+
279
+ case 'A.8.9': // Configuration Management
280
+ obligations.push({
281
+ id: 'config-firewall',
282
+ formula: 'firewall_rules.count > 0',
283
+ status: state.network.firewallRules > 0 ? 'proven' : 'disproven',
284
+ });
285
+ obligations.push({
286
+ id: 'config-segmentation',
287
+ formula: 'network_segmentation.enabled = true',
288
+ status: state.network.segmentationEnabled ? 'proven' : 'disproven',
289
+ });
290
+ obligations.push({
291
+ id: 'config-tls',
292
+ formula: 'tls_version >= 1.2',
293
+ status: ['1.2', '1.3'].includes(state.network.tlsVersion) ? 'proven' : 'disproven',
294
+ });
295
+ break;
296
+
297
+ case 'A.8.16': // Monitoring Activities
298
+ obligations.push({
299
+ id: 'mon-siem',
300
+ formula: 'siem.enabled = true',
301
+ status: state.monitoring.siemEnabled ? 'proven' : 'disproven',
302
+ });
303
+ obligations.push({
304
+ id: 'mon-retention',
305
+ formula: 'log_retention_days >= 90',
306
+ status: state.monitoring.logRetentionDays >= 90 ? 'proven' : 'disproven',
307
+ });
308
+ obligations.push({
309
+ id: 'mon-alerting',
310
+ formula: 'alerting.enabled = true',
311
+ status: state.monitoring.alertingEnabled ? 'proven' : 'disproven',
312
+ });
313
+ break;
314
+
315
+ case 'CC6.1': // SOC 2 Logical Access
316
+ obligations.push({
317
+ id: 'soc2-access-mfa',
318
+ formula: 'mfa_enabled = true',
319
+ status: state.iam.mfaEnabled ? 'proven' : 'disproven',
320
+ });
321
+ obligations.push({
322
+ id: 'soc2-access-rbac',
323
+ formula: 'rbac_policy_version != null',
324
+ status: state.iam.rbacPolicyVersion.length > 0 ? 'proven' : 'disproven',
325
+ });
326
+ obligations.push({
327
+ id: 'soc2-access-encryption',
328
+ formula: 'encryption_in_transit = true',
329
+ status: state.data.encryptionInTransit ? 'proven' : 'disproven',
330
+ });
331
+ break;
332
+
333
+ case 'CC7.2': // SOC 2 Security Event Monitoring
334
+ obligations.push({
335
+ id: 'soc2-monitor-siem',
336
+ formula: 'siem_enabled = true',
337
+ status: state.monitoring.siemEnabled ? 'proven' : 'disproven',
338
+ });
339
+ obligations.push({
340
+ id: 'soc2-monitor-coverage',
341
+ formula: 'monitoring_coverage >= 80_percent',
342
+ status: state.monitoring.monitoringCoverage >= 80 ? 'proven' : 'disproven',
343
+ });
344
+ break;
345
+
346
+ case 'A.6.1': // ISO 42001 AI Risk Assessment
347
+ obligations.push({
348
+ id: 'ai-risk-assessment',
349
+ formula: 'risk_assessment_documented = true',
350
+ status: context.currentEvidence.has(control.id) ? 'proven' : 'disproven',
351
+ });
352
+ break;
353
+
354
+ case 'PR.AC': // NIST CSF Identity Management
355
+ obligations.push({
356
+ id: 'nist-iam-mfa',
357
+ formula: 'mfa_enforced = true',
358
+ status: state.iam.mfaEnabled ? 'proven' : 'disproven',
359
+ });
360
+ obligations.push({
361
+ id: 'nist-iam-session',
362
+ formula: 'session_timeout <= 900',
363
+ status: state.iam.sessionTimeout <= 900 ? 'proven' : 'disproven',
364
+ });
365
+ break;
366
+
367
+ case 'DE.CM': // NIST CSF Continuous Monitoring
368
+ obligations.push({
369
+ id: 'nist-monitor',
370
+ formula: 'siem_enabled AND alerting_enabled',
371
+ status: (state.monitoring.siemEnabled && state.monitoring.alertingEnabled) ? 'proven' : 'disproven',
372
+ });
373
+ break;
374
+
375
+ default:
376
+ obligations.push({
377
+ id: `default-${control.id}`,
378
+ formula: 'evidence_count > 0',
379
+ status: context.currentEvidence.has(control.id) ? 'proven' : 'disproven',
380
+ });
381
+ }
382
+
383
+ return obligations;
384
+ }
385
+
386
+ private isPasswordFresh(rotationDate: string, maxAgeDays: number): boolean {
387
+ const rotation = new Date(rotationDate);
388
+ const now = new Date();
389
+ const ageDays = (now.getTime() - rotation.getTime()) / (1000 * 60 * 60 * 24);
390
+ return ageDays <= maxAgeDays;
391
+ }
392
+
393
+ private calculateConfidence(
394
+ control: ASTControlNode,
395
+ evidence: EvidenceItem[],
396
+ obligations: ProofObligation[],
397
+ _context: ReasoningContext
398
+ ): number {
399
+ let confidence = 0;
400
+
401
+ const validEvidence = evidence.filter((e) => e.valid);
402
+ const evidenceScore = Math.min(validEvidence.length / 3, 1) * 0.4;
403
+ confidence += evidenceScore;
404
+
405
+ const proven = obligations.filter((o) => o.status === 'proven').length;
406
+ const total = obligations.length;
407
+ const obligationScore = total > 0 ? (proven / total) * 0.5 : 0.5;
408
+ confidence += obligationScore;
409
+
410
+ const freshness = this.evidenceFreshnessScore(validEvidence);
411
+ confidence += freshness * 0.1;
412
+
413
+ return Math.min(confidence, 1);
414
+ }
415
+
416
+ private evidenceFreshnessScore(evidence: EvidenceItem[]): number {
417
+ if (evidence.length === 0) return 0;
418
+ const now = Date.now();
419
+ const ages = evidence.map((e) => {
420
+ const age = (now - new Date(e.timestamp).getTime()) / (1000 * 60 * 60 * 24);
421
+ return age;
422
+ });
423
+ const avgAge = ages.reduce((a, b) => a + b, 0) / ages.length;
424
+ if (avgAge <= 7) return 1;
425
+ if (avgAge <= 30) return 0.8;
426
+ if (avgAge <= 90) return 0.6;
427
+ if (avgAge <= 365) return 0.4;
428
+ return 0.2;
429
+ }
430
+
431
+ private mapDecisionToStatus(decision: string): ControlStatus['status'] {
432
+ switch (decision) {
433
+ case 'compliant': return 'compliant';
434
+ case 'non-compliant': return 'non-compliant';
435
+ case 'partial': return 'partial';
436
+ default: return 'not-tested';
437
+ }
438
+ }
439
+
440
+ private assessRisk(control: ASTControlNode, result: ReasoningResult, context: ReasoningContext): RiskAssessment {
441
+ const severityMap = { LOW: 1, MEDIUM: 3, HIGH: 7, CRITICAL: 10 };
442
+ const baseRisk = severityMap[control.severity as keyof typeof severityMap] ?? 3;
443
+
444
+ const complianceRisk = result.decision === 'compliant' ? 0 : result.decision === 'partial' ? 3 : 7;
445
+ const likelihood = complianceRisk / 10;
446
+
447
+ const blastRadius = this.calculateBlastRadius(control, context);
448
+ const impact = baseRisk * blastRadius;
449
+
450
+ const riskScore = (likelihood * 50 + impact * 50) / 10;
451
+
452
+ const factors: string[] = [];
453
+ if (result.decision === 'non-compliant') factors.push('control_non_compliant');
454
+ if (control.severity === 'CRITICAL') factors.push('critical_severity');
455
+ if (blastRadius > 0.7) factors.push('high_blast_radius');
456
+ if (context.previousState) {
457
+ const prev = context.previousState.controlStatuses.find((s) => s.controlId === control.id);
458
+ if (prev && prev.status === 'compliant') factors.push('regression_detected');
459
+ }
460
+
461
+ return {
462
+ controlId: control.id,
463
+ riskScore,
464
+ blastRadius,
465
+ likelihood,
466
+ impact,
467
+ factors,
468
+ };
469
+ }
470
+
471
+ private calculateBlastRadius(control: ASTControlNode, context: ReasoningContext): number {
472
+ const ast = this.asts.get(context.framework);
473
+ if (!ast) return 0.5;
474
+
475
+ const dependent = ast.controls.filter((c) => c.crossRefs.some((ref) => ref.includes(control.code)));
476
+ const total = ast.controls.length;
477
+
478
+ return Math.min(dependent.length / Math.max(total, 1) + 0.1, 1);
479
+ }
480
+
481
+ async detectDrift(context: ReasoningContext): Promise<DriftEvent[]> {
482
+ if (!context.previousState) return [];
483
+
484
+ const current = await this.reason(context);
485
+ const drifts: DriftEvent[] = [];
486
+
487
+ for (const prev of context.previousState.controlStatuses) {
488
+ const curr = current.controlStatuses.find((s) => s.controlId === prev.controlId);
489
+ if (curr && prev.status === 'compliant' && curr.status !== 'compliant') {
490
+ drifts.push({
491
+ id: `drift-${prev.controlId}-${Date.now()}`,
492
+ controlId: prev.controlId,
493
+ detectedAt: new Date().toISOString(),
494
+ type: 'policy',
495
+ before: prev.status,
496
+ after: curr.status,
497
+ severity: 'HIGH',
498
+ autoRemediated: false,
499
+ });
500
+ }
501
+ }
502
+
503
+ return drifts;
504
+ }
505
+
506
+ async synthesizeRemediation(drift: DriftEvent): Promise<string> {
507
+ return `REMEDIATION for ${drift.controlId}: Auto-remediation plan for ${drift.type} drift from ${drift.before} to ${drift.after}. Severity: ${drift.severity}. Apply configuration change and verify evidence.`;
508
+ }
509
+ }
package/src/test.ts ADDED
@@ -0,0 +1,148 @@
1
+ import { RegulationASTCompiler } from './compiler/RegulationASTCompiler.js';
2
+ import { NeuroSymbolicReasoner } from './reasoner/NeuroSymbolicReasoner.js';
3
+ import { UnifiedComplianceGraph } from './graph/UnifiedComplianceGraph.js';
4
+ import { ComplianceSuperOrchestrator } from './index.js';
5
+ import type { FrameworkCode } from './types.js';
6
+ import type { ReasoningContext } from './reasoner/NeuroSymbolicReasoner.js';
7
+
8
+ async function testRegulationASTCompiler() {
9
+ console.log('\n=== Testing Regulation AST Compiler ===');
10
+ const compiler = new RegulationASTCompiler();
11
+
12
+ const isoAST = compiler.getAST('iso27001');
13
+ console.log(`ISO 27001 AST compiled: ${isoAST?.controls.length} controls`);
14
+ console.log(` Families: ${isoAST?.metadata.families.join(', ')}`);
15
+ console.log(` Crosswalks: ${isoAST?.crosswalks.length}`);
16
+
17
+ const soc2AST = compiler.getAST('soc2');
18
+ console.log(`SOC 2 AST compiled: ${soc2AST?.controls.length} controls`);
19
+
20
+ const iso42001AST = compiler.getAST('iso42001');
21
+ console.log(`ISO 42001 AST compiled: ${iso42001AST?.controls.length} controls`);
22
+
23
+ const euAiAST = compiler.getAST('eu-ai-act');
24
+ console.log(`EU AI Act AST compiled: ${euAiAST?.controls.length} controls`);
25
+
26
+ const doraAST = compiler.getAST('dora');
27
+ console.log(`DORA AST compiled: ${doraAST?.controls.length} controls`);
28
+
29
+ const equiv = compiler.findEquivalent('iso27001', 'A.8.2');
30
+ console.log(`Crosswalk A.8.2 → SOC 2: ${equiv.map((e) => `${e.targetFramework}:${e.targetControl}`).join(', ')}`);
31
+
32
+ const nl = compiler.compileNaturalLanguage('iso27001', 'Organization shall implement AI model governance');
33
+ console.log(`Natural language compiled: ${nl.id}`);
34
+
35
+ console.log('✓ Regulation AST Compiler tests passed');
36
+ }
37
+
38
+ async function testNeuroSymbolicReasoner() {
39
+ console.log('\n=== Testing Neuro-Symbolic Reasoner ===');
40
+ const compiler = new RegulationASTCompiler();
41
+ const asts = compiler.getAllASTs();
42
+ const astMap = new Map(asts.map((a) => [a.framework, a]));
43
+ const reasoner = new NeuroSymbolicReasoner(astMap);
44
+
45
+ const context: ReasoningContext = {
46
+ orgId: 'test-org',
47
+ framework: 'iso27001',
48
+ currentEvidence: new Map([
49
+ ['iso-a.8.2', [{ id: 'ev-1', controlId: 'iso-a.8.2', type: 'config', hash: 'abc123', timestamp: new Date().toISOString(), valid: true }]],
50
+ ['iso-a.8.5', [{ id: 'ev-2', controlId: 'iso-a.8.5', type: 'config', hash: 'def456', timestamp: new Date().toISOString(), valid: true }]],
51
+ ]),
52
+ configurationState: {
53
+ iam: { mfaEnabled: true, privilegedUsers: ['admin', 'ops'], sessionTimeout: 900, lastPasswordRotation: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(), rbacPolicyVersion: '2.0', mfaEnforcementRate: 0.98 },
54
+ network: { firewallRules: 15, segmentationEnabled: true, idsEnabled: true, tlsVersion: '1.3', publicEndpoints: [] },
55
+ data: { encryptionAtRest: true, encryptionInTransit: true, backupEnabled: true, backupFrequency: 'daily', lastBackup: new Date().toISOString(), retentionDays: 90 },
56
+ monitoring: { siemEnabled: true, logRetentionDays: 180, alertingEnabled: true, mttr: 4, monitoringCoverage: 95 },
57
+ physical: { accessControl: true, cctvEnabled: true, environmentalMonitoring: true, visitorManagement: true },
58
+ },
59
+ riskTolerance: 'medium',
60
+ };
61
+
62
+ const state = await reasoner.reason(context);
63
+ console.log(`ISO 27001 compliance score: ${state.overallScore.toFixed(1)}%`);
64
+ console.log(` Controls evaluated: ${state.controlStatuses.length}`);
65
+ console.log(` Compliant: ${state.controlStatuses.filter((s) => s.status === 'compliant').length}`);
66
+ console.log(` Non-compliant: ${state.controlStatuses.filter((s) => s.status === 'non-compliant').length}`);
67
+ console.log(` Risks: ${state.risks.length}`);
68
+
69
+ for (const cs of state.controlStatuses.slice(0, 3)) {
70
+ console.log(` ${cs.controlId}: ${cs.status} (score: ${cs.score.toFixed(1)})`);
71
+ }
72
+
73
+ console.log('✓ Neuro-Symbolic Reasoner tests passed');
74
+ }
75
+
76
+ async function testUnifiedComplianceGraph() {
77
+ console.log('\n=== Testing Unified Compliance Graph ===');
78
+ const compiler = new RegulationASTCompiler();
79
+ const asts = compiler.getAllASTs();
80
+ const graph = new UnifiedComplianceGraph(asts);
81
+
82
+ console.log(`Graph nodes: ${graph.getGraphHash()}`);
83
+
84
+ const blastRadius = graph.calculateBlastRadius('control:iso27001:A.8.2');
85
+ console.log(`Blast radius for A.8.2: ${blastRadius.impactScore.toFixed(2)} (${blastRadius.affectedControls.length} controls)`);
86
+
87
+ const attackPaths = graph.traceAttackPaths('control:iso27001:A.8.2', 3);
88
+ console.log(`Attack paths found: ${attackPaths.length}`);
89
+
90
+ console.log('✓ Unified Compliance Graph tests passed');
91
+ }
92
+
93
+ async function testComplianceSuperOrchestrator() {
94
+ console.log('\n=== Testing Compliance Super Orchestrator ===');
95
+ const orchestrator = new ComplianceSuperOrchestrator({
96
+ orgId: 'test-org',
97
+ enabledFrameworks: ['iso27001', 'soc2', 'iso42001'],
98
+ riskTolerance: 'medium',
99
+ autoRemediate: false,
100
+ continuousScanInterval: 300000,
101
+ });
102
+
103
+ const contexts = new Map<FrameworkCode, ReasoningContext>();
104
+ const baseEvidence = new Map([
105
+ ['iso-a.8.2', [{ id: 'ev-1', controlId: 'iso-a.8.2', type: 'config', hash: 'abc', timestamp: new Date().toISOString(), valid: true }]],
106
+ ]);
107
+ const baseConfig = {
108
+ iam: { mfaEnabled: true, privilegedUsers: ['admin'], sessionTimeout: 900, lastPasswordRotation: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(), rbacPolicyVersion: '2.0', mfaEnforcementRate: 0.98 },
109
+ network: { firewallRules: 10, segmentationEnabled: true, idsEnabled: true, tlsVersion: '1.3', publicEndpoints: [] },
110
+ data: { encryptionAtRest: true, encryptionInTransit: true, backupEnabled: true, backupFrequency: 'daily', lastBackup: new Date().toISOString(), retentionDays: 90 },
111
+ monitoring: { siemEnabled: true, logRetentionDays: 180, alertingEnabled: true, mttr: 4, monitoringCoverage: 90 },
112
+ physical: { accessControl: true, cctvEnabled: true, environmentalMonitoring: true, visitorManagement: true },
113
+ };
114
+
115
+ contexts.set('iso27001', { orgId: 'test-org', framework: 'iso27001', currentEvidence: baseEvidence, configurationState: baseConfig, riskTolerance: 'medium' });
116
+ contexts.set('soc2', { orgId: 'test-org', framework: 'soc2', currentEvidence: baseEvidence, configurationState: baseConfig, riskTolerance: 'medium' });
117
+ contexts.set('iso42001', { orgId: 'test-org', framework: 'iso42001', currentEvidence: baseEvidence, configurationState: baseConfig, riskTolerance: 'medium' });
118
+
119
+ const result = await orchestrator.continuousComplianceLoop(contexts);
120
+ console.log(`Overall compliance score: ${result.overallScore.toFixed(1)}%`);
121
+ console.log(`Frameworks evaluated: ${result.states.length}`);
122
+ console.log(`Drift events: ${result.drift.length}`);
123
+ console.log(`Risks identified: ${result.risks.length}`);
124
+
125
+ const plan = await orchestrator.synthesizePlan('iso27001', result.states[0], 95);
126
+ console.log(`Remediation plan: ${plan.actions.length} actions, estimated ${plan.estimatedDuration}`);
127
+
128
+ const audit = await orchestrator.executeAudit('iso27001', contexts.get('iso27001')!);
129
+ console.log(`Audit result: ${audit.summary.passed}/${audit.summary.totalControls} passed`);
130
+
131
+ console.log('✓ Compliance Super Orchestrator tests passed');
132
+ }
133
+
134
+ async function runAllTests() {
135
+ console.log('Starting Compliance Orchestrator Tests...\n');
136
+ console.log('='.repeat(60));
137
+
138
+ await testRegulationASTCompiler();
139
+ await testNeuroSymbolicReasoner();
140
+ await testUnifiedComplianceGraph();
141
+ await testComplianceSuperOrchestrator();
142
+
143
+ console.log('\n' + '='.repeat(60));
144
+ console.log('All Compliance Orchestrator tests passed! ✓');
145
+ console.log('='.repeat(60));
146
+ }
147
+
148
+ runAllTests().catch(console.error);