guardrail-compliance 1.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.
- package/dist/audit/emitter.d.ts +97 -0
- package/dist/audit/emitter.d.ts.map +1 -0
- package/dist/audit/emitter.js +197 -0
- package/dist/audit/events.d.ts +304 -0
- package/dist/audit/events.d.ts.map +1 -0
- package/dist/audit/events.js +267 -0
- package/dist/audit/index.d.ts +11 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +51 -0
- package/dist/audit/storage.d.ts +93 -0
- package/dist/audit/storage.d.ts.map +1 -0
- package/dist/audit/storage.js +337 -0
- package/dist/automation/__tests__/compliance-scheduler.test.d.ts +2 -0
- package/dist/automation/__tests__/compliance-scheduler.test.d.ts.map +1 -0
- package/dist/automation/__tests__/compliance-scheduler.test.js +140 -0
- package/dist/automation/audit-logger.d.ts +129 -0
- package/dist/automation/audit-logger.d.ts.map +1 -0
- package/dist/automation/audit-logger.js +473 -0
- package/dist/automation/compliance-scheduler-fixed.d.ts +1 -0
- package/dist/automation/compliance-scheduler-fixed.d.ts.map +1 -0
- package/dist/automation/compliance-scheduler-fixed.js +1 -0
- package/dist/automation/compliance-scheduler.d.ts +83 -0
- package/dist/automation/compliance-scheduler.d.ts.map +1 -0
- package/dist/automation/compliance-scheduler.js +414 -0
- package/dist/automation/dashboard.d.ts +194 -0
- package/dist/automation/dashboard.d.ts.map +1 -0
- package/dist/automation/dashboard.js +768 -0
- package/dist/automation/email-service.d.ts +69 -0
- package/dist/automation/email-service.d.ts.map +1 -0
- package/dist/automation/email-service.js +218 -0
- package/dist/automation/evidence-collector.d.ts +140 -0
- package/dist/automation/evidence-collector.d.ts.map +1 -0
- package/dist/automation/evidence-collector.js +682 -0
- package/dist/automation/index.d.ts +8 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js +24 -0
- package/dist/automation/pdf-exporter.d.ts +90 -0
- package/dist/automation/pdf-exporter.d.ts.map +1 -0
- package/dist/automation/pdf-exporter.js +381 -0
- package/dist/automation/reporting-engine.d.ts +116 -0
- package/dist/automation/reporting-engine.d.ts.map +1 -0
- package/dist/automation/reporting-engine.js +329 -0
- package/dist/container/index.d.ts +4 -0
- package/dist/container/index.d.ts.map +1 -0
- package/dist/container/index.js +19 -0
- package/dist/container/kubernetes.d.ts +94 -0
- package/dist/container/kubernetes.d.ts.map +1 -0
- package/dist/container/kubernetes.js +268 -0
- package/dist/container/rules.d.ts +27 -0
- package/dist/container/rules.d.ts.map +1 -0
- package/dist/container/rules.js +216 -0
- package/dist/container/scanner.d.ts +50 -0
- package/dist/container/scanner.d.ts.map +1 -0
- package/dist/container/scanner.js +143 -0
- package/dist/frameworks/engine.d.ts +108 -0
- package/dist/frameworks/engine.d.ts.map +1 -0
- package/dist/frameworks/engine.js +206 -0
- package/dist/frameworks/gdpr.d.ts +6 -0
- package/dist/frameworks/gdpr.d.ts.map +1 -0
- package/dist/frameworks/gdpr.js +198 -0
- package/dist/frameworks/hipaa.d.ts +6 -0
- package/dist/frameworks/hipaa.d.ts.map +1 -0
- package/dist/frameworks/hipaa.js +183 -0
- package/dist/frameworks/index.d.ts +8 -0
- package/dist/frameworks/index.d.ts.map +1 -0
- package/dist/frameworks/index.js +30 -0
- package/dist/frameworks/iso27001.d.ts +63 -0
- package/dist/frameworks/iso27001.d.ts.map +1 -0
- package/dist/frameworks/iso27001.js +331 -0
- package/dist/frameworks/nist.d.ts +62 -0
- package/dist/frameworks/nist.d.ts.map +1 -0
- package/dist/frameworks/nist.js +424 -0
- package/dist/frameworks/pci.d.ts +6 -0
- package/dist/frameworks/pci.d.ts.map +1 -0
- package/dist/frameworks/pci.js +201 -0
- package/dist/frameworks/soc2.d.ts +7 -0
- package/dist/frameworks/soc2.d.ts.map +1 -0
- package/dist/frameworks/soc2.js +248 -0
- package/dist/iac/drift-detector.d.ts +64 -0
- package/dist/iac/drift-detector.d.ts.map +1 -0
- package/dist/iac/drift-detector.js +134 -0
- package/dist/iac/index.d.ts +4 -0
- package/dist/iac/index.d.ts.map +1 -0
- package/dist/iac/index.js +19 -0
- package/dist/iac/rules.d.ts +17 -0
- package/dist/iac/rules.d.ts.map +1 -0
- package/dist/iac/rules.js +385 -0
- package/dist/iac/scanner.d.ts +104 -0
- package/dist/iac/scanner.d.ts.map +1 -0
- package/dist/iac/scanner.js +343 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/pii/data-flow.d.ts +58 -0
- package/dist/pii/data-flow.d.ts.map +1 -0
- package/dist/pii/data-flow.js +154 -0
- package/dist/pii/detector.d.ts +60 -0
- package/dist/pii/detector.d.ts.map +1 -0
- package/dist/pii/detector.js +267 -0
- package/dist/pii/index.d.ts +4 -0
- package/dist/pii/index.d.ts.map +1 -0
- package/dist/pii/index.js +19 -0
- package/dist/pii/patterns.d.ts +36 -0
- package/dist/pii/patterns.d.ts.map +1 -0
- package/dist/pii/patterns.js +108 -0
- package/dist/policy/index.d.ts +5 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +20 -0
- package/dist/policy/opa-engine.d.ts +121 -0
- package/dist/policy/opa-engine.d.ts.map +1 -0
- package/dist/policy/opa-engine.js +423 -0
- package/package.json +31 -0
- package/src/audit/emitter.ts +383 -0
- package/src/audit/events.ts +351 -0
- package/src/audit/index.ts +35 -0
- package/src/audit/storage.ts +394 -0
- package/src/automation/__tests__/compliance-scheduler.test.ts +183 -0
- package/src/automation/audit-logger.ts +629 -0
- package/src/automation/compliance-scheduler-fixed.ts +0 -0
- package/src/automation/compliance-scheduler.ts +516 -0
- package/src/automation/dashboard.ts +947 -0
- package/src/automation/email-service.ts +230 -0
- package/src/automation/evidence-collector.ts +866 -0
- package/src/automation/index.ts +8 -0
- package/src/automation/pdf-exporter.ts +434 -0
- package/src/automation/reporting-engine.ts +462 -0
- package/src/container/index.ts +3 -0
- package/src/container/kubernetes.ts +379 -0
- package/src/container/rules.ts +244 -0
- package/src/container/scanner.ts +202 -0
- package/src/frameworks/engine.ts +298 -0
- package/src/frameworks/gdpr.ts +204 -0
- package/src/frameworks/hipaa.ts +209 -0
- package/src/frameworks/index.ts +23 -0
- package/src/frameworks/iso27001.ts +398 -0
- package/src/frameworks/nist.ts +518 -0
- package/src/frameworks/pci.ts +226 -0
- package/src/frameworks/soc2.ts +281 -0
- package/src/iac/drift-detector.ts +197 -0
- package/src/iac/index.ts +3 -0
- package/src/iac/rules.ts +420 -0
- package/src/iac/scanner.ts +445 -0
- package/src/index.ts +17 -0
- package/src/pii/data-flow.ts +216 -0
- package/src/pii/detector.ts +327 -0
- package/src/pii/index.ts +3 -0
- package/src/pii/patterns.ts +128 -0
- package/src/policy/index.ts +5 -0
- package/src/policy/opa-engine.ts +504 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import { prisma } from "@guardrail/database";
|
|
2
|
+
import { ComplianceAssessmentResult } from "../frameworks/engine";
|
|
3
|
+
import { EvidenceArtifact } from "./evidence-collector";
|
|
4
|
+
import { auditLogger } from "./audit-logger";
|
|
5
|
+
|
|
6
|
+
interface ReportRequest {
|
|
7
|
+
projectId: string;
|
|
8
|
+
frameworkId: string;
|
|
9
|
+
type: "compliance" | "audit" | "executive" | "technical" | "remediation";
|
|
10
|
+
format: "pdf" | "html" | "json" | "csv";
|
|
11
|
+
period?: {
|
|
12
|
+
start: Date;
|
|
13
|
+
end: Date;
|
|
14
|
+
};
|
|
15
|
+
includeEvidence?: boolean;
|
|
16
|
+
includeRecommendations?: boolean;
|
|
17
|
+
includeCharts?: boolean;
|
|
18
|
+
recipients?: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ComplianceReport {
|
|
22
|
+
id: string;
|
|
23
|
+
projectId: string;
|
|
24
|
+
frameworkId: string;
|
|
25
|
+
type: string;
|
|
26
|
+
format: string;
|
|
27
|
+
generatedAt: Date;
|
|
28
|
+
period?: {
|
|
29
|
+
start: Date;
|
|
30
|
+
end: Date;
|
|
31
|
+
};
|
|
32
|
+
summary: {
|
|
33
|
+
overallScore: number;
|
|
34
|
+
status: "compliant" | "partial" | "non-compliant";
|
|
35
|
+
totalControls: number;
|
|
36
|
+
compliantControls: number;
|
|
37
|
+
partialControls: number;
|
|
38
|
+
nonCompliantControls: number;
|
|
39
|
+
highRiskGaps: number;
|
|
40
|
+
mediumRiskGaps: number;
|
|
41
|
+
lowRiskGaps: number;
|
|
42
|
+
};
|
|
43
|
+
sections: ReportSection[];
|
|
44
|
+
evidence?: EvidenceArtifact[];
|
|
45
|
+
recommendations: Recommendation[];
|
|
46
|
+
charts?: ChartData[];
|
|
47
|
+
metadata: {
|
|
48
|
+
version: string;
|
|
49
|
+
generatedBy: string;
|
|
50
|
+
reviewStatus?: "pending" | "approved" | "rejected";
|
|
51
|
+
reviewedBy?: string;
|
|
52
|
+
reviewedAt?: Date;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface ReportSection {
|
|
57
|
+
id: string;
|
|
58
|
+
title: string;
|
|
59
|
+
type: "summary" | "details" | "evidence" | "recommendations" | "appendix";
|
|
60
|
+
content: any;
|
|
61
|
+
order: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface Recommendation {
|
|
65
|
+
id: string;
|
|
66
|
+
controlId: string;
|
|
67
|
+
priority: "critical" | "high" | "medium" | "low";
|
|
68
|
+
category: string;
|
|
69
|
+
title: string;
|
|
70
|
+
description: string;
|
|
71
|
+
impact: string;
|
|
72
|
+
effort: "low" | "medium" | "high";
|
|
73
|
+
dueDate?: Date;
|
|
74
|
+
assignedTo?: string;
|
|
75
|
+
status: "open" | "in-progress" | "completed" | "deferred";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface ChartData {
|
|
79
|
+
id: string;
|
|
80
|
+
type: "pie" | "bar" | "line" | "heatmap";
|
|
81
|
+
title: string;
|
|
82
|
+
data: any;
|
|
83
|
+
description?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Automated Compliance Reporting Engine
|
|
88
|
+
*
|
|
89
|
+
* Generates comprehensive compliance reports with evidence,
|
|
90
|
+
* recommendations, and visual analytics
|
|
91
|
+
*/
|
|
92
|
+
export class ReportingEngine {
|
|
93
|
+
private readonly reportTemplates = new Map();
|
|
94
|
+
|
|
95
|
+
constructor() {
|
|
96
|
+
this.initializeTemplates();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Generate compliance report
|
|
101
|
+
*/
|
|
102
|
+
async generateReport(
|
|
103
|
+
request: ReportRequest & {
|
|
104
|
+
assessment?: ComplianceAssessmentResult;
|
|
105
|
+
evidence?: EvidenceArtifact[];
|
|
106
|
+
},
|
|
107
|
+
): Promise<ComplianceReport> {
|
|
108
|
+
// Get project details
|
|
109
|
+
const project = await prisma.project.findUnique({
|
|
110
|
+
where: { id: request.projectId },
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (!project) {
|
|
114
|
+
throw new Error(`Project ${request.projectId} not found`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Get assessment if not provided
|
|
118
|
+
let assessment = request.assessment;
|
|
119
|
+
if (!assessment) {
|
|
120
|
+
const latest = await prisma.complianceAssessment.findFirst({
|
|
121
|
+
where: {
|
|
122
|
+
projectId: request.projectId,
|
|
123
|
+
frameworkId: request.frameworkId,
|
|
124
|
+
},
|
|
125
|
+
orderBy: { createdAt: "desc" },
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (!latest) {
|
|
129
|
+
throw new Error("No assessment found for this project and framework");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Convert database record to assessment result with proper type handling
|
|
133
|
+
assessment = {
|
|
134
|
+
projectId: latest.projectId,
|
|
135
|
+
frameworkId: latest.frameworkId,
|
|
136
|
+
summary: (latest.summary as any) || {
|
|
137
|
+
totalControls: 0,
|
|
138
|
+
compliant: 0,
|
|
139
|
+
partial: 0,
|
|
140
|
+
nonCompliant: 0,
|
|
141
|
+
score: 0,
|
|
142
|
+
},
|
|
143
|
+
evidence: (latest.evidence as any) || [],
|
|
144
|
+
controls: (latest.controls as any) || [],
|
|
145
|
+
gaps: (latest.gaps as any) || [],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Get evidence if requested
|
|
150
|
+
let evidence = request.evidence;
|
|
151
|
+
if (request.includeEvidence && !evidence) {
|
|
152
|
+
// For now, skip evidence collection if no database table exists
|
|
153
|
+
evidence = [];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Generate report ID
|
|
157
|
+
const reportId = `report_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
158
|
+
|
|
159
|
+
// Build report sections based on type
|
|
160
|
+
if (!assessment) {
|
|
161
|
+
throw new Error("No assessment data available");
|
|
162
|
+
}
|
|
163
|
+
const sections = await this.buildSections(
|
|
164
|
+
request.type,
|
|
165
|
+
assessment,
|
|
166
|
+
evidence,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Generate recommendations if needed
|
|
170
|
+
const recommendations = request.includeRecommendations
|
|
171
|
+
? await this.generateRecommendations(assessment!)
|
|
172
|
+
: [];
|
|
173
|
+
|
|
174
|
+
// Generate charts if needed
|
|
175
|
+
const charts = request.includeCharts
|
|
176
|
+
? await this.generateCharts(assessment!)
|
|
177
|
+
: [];
|
|
178
|
+
|
|
179
|
+
// Create report
|
|
180
|
+
const report: ComplianceReport = {
|
|
181
|
+
id: reportId,
|
|
182
|
+
projectId: request.projectId,
|
|
183
|
+
frameworkId: request.frameworkId,
|
|
184
|
+
type: request.type,
|
|
185
|
+
format: request.format,
|
|
186
|
+
generatedAt: new Date(),
|
|
187
|
+
period: request.period,
|
|
188
|
+
summary: this.generateSummary(assessment!),
|
|
189
|
+
sections, // Use the sections we already built
|
|
190
|
+
evidence: request.includeEvidence ? evidence : undefined,
|
|
191
|
+
recommendations, // Use the recommendations we already built
|
|
192
|
+
charts, // Use the charts we already built
|
|
193
|
+
metadata: {
|
|
194
|
+
version: "1.0",
|
|
195
|
+
generatedBy: "Guardrail Compliance Engine",
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Save report to database - skip if table doesn't exist
|
|
200
|
+
try {
|
|
201
|
+
await this.saveReport(report);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.warn("Could not save report to database:", error);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Log report generation
|
|
207
|
+
await auditLogger.logEvent({
|
|
208
|
+
type: "report_generated",
|
|
209
|
+
category: "compliance",
|
|
210
|
+
projectId: request.projectId,
|
|
211
|
+
frameworkId: request.frameworkId,
|
|
212
|
+
timestamp: new Date(),
|
|
213
|
+
severity: "low",
|
|
214
|
+
source: "reporting-engine",
|
|
215
|
+
metadata: {
|
|
216
|
+
reportId,
|
|
217
|
+
type: request.type,
|
|
218
|
+
format: request.format,
|
|
219
|
+
includeEvidence: request.includeEvidence,
|
|
220
|
+
recipientCount: request.recipients?.length || 0,
|
|
221
|
+
},
|
|
222
|
+
details: {
|
|
223
|
+
action: "Compliance report generated",
|
|
224
|
+
reportId,
|
|
225
|
+
type: request.type,
|
|
226
|
+
score: report.summary.overallScore,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Send report if recipients specified
|
|
231
|
+
if (request.recipients?.length) {
|
|
232
|
+
await this.sendReport(report, request.recipients);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return report;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get report by ID
|
|
240
|
+
*/
|
|
241
|
+
async getReport(reportId: string): Promise<ComplianceReport | null> {
|
|
242
|
+
try {
|
|
243
|
+
const report = await prisma.complianceReport.findUnique({
|
|
244
|
+
where: { id: reportId },
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
if (!report) return null;
|
|
248
|
+
|
|
249
|
+
// Convert database report to ComplianceReport format
|
|
250
|
+
// @ts-ignore - Prisma client type issue
|
|
251
|
+
return {
|
|
252
|
+
id: report.id,
|
|
253
|
+
projectId: report.projectId,
|
|
254
|
+
frameworkId: (report as any).frameworkId,
|
|
255
|
+
type: (report as any).type,
|
|
256
|
+
format: (report as any).format,
|
|
257
|
+
generatedAt: (report as any).generatedAt || report.createdAt,
|
|
258
|
+
period: (report as any).period,
|
|
259
|
+
summary: report.summary as any,
|
|
260
|
+
sections: (report as any).sections || [],
|
|
261
|
+
evidence: (report as any).evidence || undefined,
|
|
262
|
+
recommendations: (report as any).recommendations || [],
|
|
263
|
+
charts: (report as any).charts || [],
|
|
264
|
+
metadata: (report as any).metadata || {
|
|
265
|
+
version: "1.0",
|
|
266
|
+
generatedBy: "Guardrail Compliance Engine",
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.warn("Could not retrieve report from database:", error);
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* List reports for project
|
|
277
|
+
*/
|
|
278
|
+
async listReports(
|
|
279
|
+
projectId: string,
|
|
280
|
+
frameworkId?: string,
|
|
281
|
+
limit: number = 50,
|
|
282
|
+
): Promise<ComplianceReport[]> {
|
|
283
|
+
try {
|
|
284
|
+
const reports = await prisma.complianceReport.findMany({
|
|
285
|
+
where: {
|
|
286
|
+
projectId,
|
|
287
|
+
...(frameworkId && { frameworkId }),
|
|
288
|
+
},
|
|
289
|
+
orderBy: { createdAt: "desc" },
|
|
290
|
+
take: limit,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Convert database reports to ComplianceReport format
|
|
294
|
+
// @ts-ignore - Prisma client type issue
|
|
295
|
+
return reports.map((report: any) => ({
|
|
296
|
+
id: report.id,
|
|
297
|
+
projectId: report.projectId,
|
|
298
|
+
frameworkId: report.frameworkId,
|
|
299
|
+
type: report.type,
|
|
300
|
+
format: report.format,
|
|
301
|
+
generatedAt: report.generatedAt || report.createdAt,
|
|
302
|
+
period: report.period,
|
|
303
|
+
summary: report.summary as any,
|
|
304
|
+
sections: report.sections || [],
|
|
305
|
+
evidence: report.evidence || undefined,
|
|
306
|
+
recommendations: report.recommendations || [],
|
|
307
|
+
charts: report.charts || [],
|
|
308
|
+
metadata: report.metadata || {
|
|
309
|
+
version: "1.0",
|
|
310
|
+
generatedBy: "Guardrail Compliance Engine",
|
|
311
|
+
},
|
|
312
|
+
}));
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.warn("Could not retrieve reports from database:", error);
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Delete report
|
|
321
|
+
*/
|
|
322
|
+
async deleteReport(reportId: string): Promise<void> {
|
|
323
|
+
try {
|
|
324
|
+
await prisma.complianceReport.delete({
|
|
325
|
+
where: { id: reportId },
|
|
326
|
+
});
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.warn("Could not delete report from database:", error);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private async saveReport(report: ComplianceReport): Promise<void> {
|
|
333
|
+
// @ts-ignore - Prisma client type issue
|
|
334
|
+
await prisma.complianceReport.create({
|
|
335
|
+
data: {
|
|
336
|
+
projectId: report.projectId,
|
|
337
|
+
title: `${report.type} Report - ${report.frameworkId}` as any,
|
|
338
|
+
content: report as any,
|
|
339
|
+
summary: report.summary as any,
|
|
340
|
+
status: "draft",
|
|
341
|
+
} as any,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
private async sendReport(
|
|
346
|
+
report: ComplianceReport,
|
|
347
|
+
recipients: string[],
|
|
348
|
+
): Promise<void> {
|
|
349
|
+
// In production, implement email delivery service
|
|
350
|
+
console.log(`Sending report ${report.id} to ${recipients.join(", ")}`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private initializeTemplates(): void {
|
|
354
|
+
// Initialize report templates
|
|
355
|
+
this.reportTemplates.set("compliance", "standard-compliance-template");
|
|
356
|
+
this.reportTemplates.set("audit", "audit-report-template");
|
|
357
|
+
this.reportTemplates.set("executive", "executive-summary-template");
|
|
358
|
+
this.reportTemplates.set("technical", "technical-detail-template");
|
|
359
|
+
this.reportTemplates.set("remediation", "remediation-plan-template");
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private async buildSections(
|
|
363
|
+
_type: string,
|
|
364
|
+
assessment: ComplianceAssessmentResult,
|
|
365
|
+
evidence?: EvidenceArtifact[],
|
|
366
|
+
): Promise<ReportSection[]> {
|
|
367
|
+
const sections: ReportSection[] = [
|
|
368
|
+
{
|
|
369
|
+
id: "summary",
|
|
370
|
+
title: "Executive Summary",
|
|
371
|
+
type: "summary",
|
|
372
|
+
content: assessment.summary,
|
|
373
|
+
order: 1,
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
id: "details",
|
|
377
|
+
title: "Compliance Details",
|
|
378
|
+
type: "details",
|
|
379
|
+
content: {
|
|
380
|
+
controls: assessment.controls,
|
|
381
|
+
gaps: assessment.gaps,
|
|
382
|
+
},
|
|
383
|
+
order: 2,
|
|
384
|
+
},
|
|
385
|
+
];
|
|
386
|
+
|
|
387
|
+
if (evidence && evidence.length > 0) {
|
|
388
|
+
sections.push({
|
|
389
|
+
id: "evidence",
|
|
390
|
+
title: "Evidence",
|
|
391
|
+
type: "evidence",
|
|
392
|
+
content: evidence,
|
|
393
|
+
order: 3,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return sections;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private async generateRecommendations(
|
|
401
|
+
assessment: ComplianceAssessmentResult,
|
|
402
|
+
): Promise<Recommendation[]> {
|
|
403
|
+
// Generate recommendations based on gaps and failed controls
|
|
404
|
+
const recommendations: Recommendation[] = [];
|
|
405
|
+
|
|
406
|
+
for (const gap of assessment.gaps) {
|
|
407
|
+
recommendations.push({
|
|
408
|
+
id: `rec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
409
|
+
controlId: gap.controlId,
|
|
410
|
+
priority: gap.severity as any,
|
|
411
|
+
category: "compliance",
|
|
412
|
+
title: `Address compliance gap for ${gap.controlId}`,
|
|
413
|
+
description: gap.description,
|
|
414
|
+
impact: "Non-compliance risk",
|
|
415
|
+
effort: "medium",
|
|
416
|
+
status: "open",
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return recommendations;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
private async generateCharts(
|
|
424
|
+
assessment: ComplianceAssessmentResult,
|
|
425
|
+
): Promise<ChartData[]> {
|
|
426
|
+
return [
|
|
427
|
+
{
|
|
428
|
+
id: "chart_compliance_score",
|
|
429
|
+
type: "pie",
|
|
430
|
+
title: "Compliance Score Distribution",
|
|
431
|
+
data: {
|
|
432
|
+
compliant: assessment.summary.compliant,
|
|
433
|
+
partial: assessment.summary.partial,
|
|
434
|
+
nonCompliant: assessment.summary.nonCompliant,
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
];
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
private generateSummary(assessment: ComplianceAssessmentResult): any {
|
|
441
|
+
return {
|
|
442
|
+
overallScore: assessment.summary.score,
|
|
443
|
+
status:
|
|
444
|
+
assessment.summary.score >= 90
|
|
445
|
+
? "compliant"
|
|
446
|
+
: assessment.summary.score >= 70
|
|
447
|
+
? "partial"
|
|
448
|
+
: "non-compliant",
|
|
449
|
+
totalControls: assessment.summary.totalControls,
|
|
450
|
+
compliantControls: assessment.summary.compliant,
|
|
451
|
+
partialControls: assessment.summary.partial,
|
|
452
|
+
nonCompliantControls: assessment.summary.nonCompliant,
|
|
453
|
+
highRiskGaps: assessment.gaps.filter((g) => g.severity === "high").length,
|
|
454
|
+
mediumRiskGaps: assessment.gaps.filter((g) => g.severity === "medium")
|
|
455
|
+
.length,
|
|
456
|
+
lowRiskGaps: assessment.gaps.filter((g) => g.severity === "low").length,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Export singleton instance
|
|
462
|
+
export const reportingEngine = new ReportingEngine();
|