/** * SDK ZIP Export * Packages SDK state, documents, and a PDF report into a ZIP archive */ import JSZip from 'jszip' import { SDKState, SDK_STEPS } from './types' import { ExportOptions, DEFAULT_OPTIONS, formatDate, exportToPDF } from './export-pdf' // ============================================================================= // ZIP EXPORT // ============================================================================= export async function exportToZIP(state: SDKState, options: ExportOptions = {}): Promise { const opts = { ...DEFAULT_OPTIONS, ...options } const zip = new JSZip() const rootFolder = zip.folder('ai-compliance-sdk-export') if (!rootFolder) throw new Error('Failed to create ZIP folder') const phase1Folder = rootFolder.folder('phase1-assessment') const phase2Folder = rootFolder.folder('phase2-documents') const dataFolder = rootFolder.folder('data') // Main State JSON if (opts.includeRawData && dataFolder) { dataFolder.file('state.json', JSON.stringify(state, null, 2)) } // README const readmeContent = `# AI Compliance SDK Export Generated: ${formatDate(new Date())} Tenant: ${state.tenantId} Version: ${state.version} ## Folder Structure - **phase1-assessment/**: Compliance Assessment Ergebnisse - use-cases.json: Alle Use Cases - risks.json: Identifizierte Risiken - controls.json: Definierte Controls - requirements.json: Compliance-Anforderungen - **phase2-documents/**: Generierte Dokumente - dsfa.json: Datenschutz-Folgenabschaetzung - toms.json: Technische und organisatorische Massnahmen - vvt.json: Verarbeitungsverzeichnis - documents.json: Rechtliche Dokumente - **data/**: Rohdaten - state.json: Kompletter SDK State ## Progress Phase 1: ${SDK_STEPS.filter(s => s.phase === 1 && state.completedSteps.includes(s.id)).length}/${SDK_STEPS.filter(s => s.phase === 1).length} completed Phase 2: ${SDK_STEPS.filter(s => s.phase === 2 && state.completedSteps.includes(s.id)).length}/${SDK_STEPS.filter(s => s.phase === 2).length} completed ## Key Metrics - Use Cases: ${state.useCases.length} - Risks: ${state.risks.length} - Controls: ${state.controls.length} - Requirements: ${state.requirements.length} - Evidence: ${state.evidence.length} ` rootFolder.file('README.md', readmeContent) // Phase 1 Files if (phase1Folder) { phase1Folder.file('use-cases.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.useCases.length, useCases: state.useCases, }, null, 2)) phase1Folder.file('risks.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.risks.length, risks: state.risks, summary: { critical: state.risks.filter(r => r.severity === 'CRITICAL').length, high: state.risks.filter(r => r.severity === 'HIGH').length, medium: state.risks.filter(r => r.severity === 'MEDIUM').length, low: state.risks.filter(r => r.severity === 'LOW').length, }, }, null, 2)) phase1Folder.file('controls.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.controls.length, controls: state.controls, }, null, 2)) phase1Folder.file('requirements.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.requirements.length, requirements: state.requirements, }, null, 2)) phase1Folder.file('modules.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.modules.length, modules: state.modules, }, null, 2)) if (opts.includeEvidence) { phase1Folder.file('evidence.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.evidence.length, evidence: state.evidence, }, null, 2)) } phase1Folder.file('checkpoints.json', JSON.stringify({ exportedAt: new Date().toISOString(), checkpoints: state.checkpoints, }, null, 2)) if (state.screening) { phase1Folder.file('screening.json', JSON.stringify({ exportedAt: new Date().toISOString(), screening: state.screening, }, null, 2)) } } // Phase 2 Files if (phase2Folder) { if (state.dsfa) { phase2Folder.file('dsfa.json', JSON.stringify({ exportedAt: new Date().toISOString(), dsfa: state.dsfa, }, null, 2)) } phase2Folder.file('toms.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.toms.length, toms: state.toms, }, null, 2)) phase2Folder.file('vvt.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.vvt.length, processingActivities: state.vvt, }, null, 2)) if (opts.includeDocuments) { phase2Folder.file('documents.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.documents.length, documents: state.documents, }, null, 2)) } if (state.cookieBanner) { phase2Folder.file('cookie-banner.json', JSON.stringify({ exportedAt: new Date().toISOString(), config: state.cookieBanner, }, null, 2)) } phase2Folder.file('retention-policies.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.retentionPolicies.length, policies: state.retentionPolicies, }, null, 2)) if (state.aiActClassification) { phase2Folder.file('ai-act-classification.json', JSON.stringify({ exportedAt: new Date().toISOString(), classification: state.aiActClassification, }, null, 2)) } phase2Folder.file('obligations.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.obligations.length, obligations: state.obligations, }, null, 2)) phase2Folder.file('consents.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.consents.length, consents: state.consents, }, null, 2)) if (state.dsrConfig) { phase2Folder.file('dsr-config.json', JSON.stringify({ exportedAt: new Date().toISOString(), config: state.dsrConfig, }, null, 2)) } phase2Folder.file('escalation-workflows.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.escalationWorkflows.length, workflows: state.escalationWorkflows, }, null, 2)) } // Security Data if (dataFolder) { if (state.sbom) { dataFolder.file('sbom.json', JSON.stringify({ exportedAt: new Date().toISOString(), sbom: state.sbom, }, null, 2)) } if (state.securityIssues.length > 0) { dataFolder.file('security-issues.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.securityIssues.length, issues: state.securityIssues, }, null, 2)) } if (state.securityBacklog.length > 0) { dataFolder.file('security-backlog.json', JSON.stringify({ exportedAt: new Date().toISOString(), count: state.securityBacklog.length, backlog: state.securityBacklog, }, null, 2)) } } // Generate PDF and include in ZIP try { const pdfBlob = await exportToPDF(state, options) const pdfArrayBuffer = await pdfBlob.arrayBuffer() rootFolder.file('compliance-report.pdf', pdfArrayBuffer) } catch (error) { console.error('Failed to generate PDF for ZIP:', error) } return zip.generateAsync({ type: 'blob', compression: 'DEFLATE' }) }