Initial commit: breakpilot-compliance - Compliance SDK Platform

Services: Admin-Compliance, Backend-Compliance,
AI-Compliance-SDK, Consent-SDK, Developer-Portal,
PCA-Platform, DSMS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-11 23:47:28 +01:00
commit 4435e7ea0a
734 changed files with 251369 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
/**
* Compliance Module
*
* General compliance functionality including controls, evidence,
* AI Act, NIS2, and regulatory obligations
*/
import type {
Control,
Evidence,
Requirement,
Obligation,
AIActResult,
AIActRiskCategory,
RegulationCode,
ComplianceScore,
SDKState,
RiskSeverity,
} from '@breakpilot/compliance-sdk-types'
import { ComplianceClient } from '../client'
export class ComplianceModule {
private client: ComplianceClient
private getState: () => SDKState
constructor(client: ComplianceClient, getState: () => SDKState) {
this.client = client
this.getState = getState
}
// ---------------------------------------------------------------------------
// Controls
// ---------------------------------------------------------------------------
getControls(): Control[] {
return this.getState().controls
}
getControlById(id: string): Control | undefined {
return this.getState().controls.find(c => c.id === id)
}
getControlsByDomain(domain: string): Control[] {
return this.getState().controls.filter(c => c.domain === domain)
}
getControlsByStatus(status: string): Control[] {
return this.getState().controls.filter(c => c.implementationStatus === status)
}
getControlComplianceRate(): number {
const controls = this.getControls()
if (controls.length === 0) return 0
const implemented = controls.filter(c => c.implementationStatus === 'IMPLEMENTED').length
return Math.round((implemented / controls.length) * 100)
}
// ---------------------------------------------------------------------------
// Evidence
// ---------------------------------------------------------------------------
getEvidence(): Evidence[] {
return this.getState().evidence
}
getEvidenceById(id: string): Evidence | undefined {
return this.getState().evidence.find(e => e.id === id)
}
getEvidenceByControlId(controlId: string): Evidence[] {
return this.getState().evidence.filter(e => e.controlId === controlId)
}
getExpiringEvidence(days: number = 30): Evidence[] {
const cutoff = new Date()
cutoff.setDate(cutoff.getDate() + days)
return this.getState().evidence.filter(e => {
if (!e.validUntil) return false
const validUntil = new Date(e.validUntil)
return validUntil <= cutoff && e.status === 'ACTIVE'
})
}
// ---------------------------------------------------------------------------
// Requirements
// ---------------------------------------------------------------------------
getRequirements(): Requirement[] {
return this.getState().requirements
}
getRequirementsByRegulation(regulation: RegulationCode): Requirement[] {
return this.getState().requirements.filter(r => r.regulationCode === regulation)
}
getRequirementComplianceRate(regulation?: RegulationCode): number {
let requirements = this.getRequirements()
if (regulation) {
requirements = requirements.filter(r => r.regulationCode === regulation)
}
if (requirements.length === 0) return 0
const implemented = requirements.filter(
r => r.status === 'IMPLEMENTED' || r.status === 'VERIFIED'
).length
return Math.round((implemented / requirements.length) * 100)
}
// ---------------------------------------------------------------------------
// Obligations
// ---------------------------------------------------------------------------
getObligations(): Obligation[] {
return this.getState().obligations
}
getUpcomingObligations(days: number = 30): Obligation[] {
const cutoff = new Date()
cutoff.setDate(cutoff.getDate() + days)
return this.getState().obligations.filter(o => {
if (!o.deadline || o.status === 'COMPLETED') return false
const deadline = new Date(o.deadline)
return deadline <= cutoff
})
}
getOverdueObligations(): Obligation[] {
const now = new Date()
return this.getState().obligations.filter(o => {
if (!o.deadline || o.status === 'COMPLETED') return false
const deadline = new Date(o.deadline)
return deadline < now
})
}
// ---------------------------------------------------------------------------
// AI Act
// ---------------------------------------------------------------------------
getAIActClassification(): AIActResult | null {
return this.getState().aiActClassification
}
getAIActRiskCategory(): AIActRiskCategory | null {
return this.getState().aiActClassification?.riskCategory ?? null
}
isHighRiskAI(): boolean {
const category = this.getAIActRiskCategory()
return category === 'HIGH' || category === 'UNACCEPTABLE'
}
// ---------------------------------------------------------------------------
// Compliance Score
// ---------------------------------------------------------------------------
calculateComplianceScore(): ComplianceScore {
const state = this.getState()
// Calculate overall score based on controls, requirements, and evidence
const controlScore = this.getControlComplianceRate()
const requirementScore = this.getRequirementComplianceRate()
const evidenceCoverage = this.calculateEvidenceCoverage()
const overall = Math.round((controlScore + requirementScore + evidenceCoverage) / 3)
// Calculate scores by regulation
const byRegulation: Record<string, number> = {}
const regulations = new Set(state.requirements.map(r => r.regulationCode))
regulations.forEach(reg => {
byRegulation[reg] = this.getRequirementComplianceRate(reg as RegulationCode)
})
// Calculate scores by domain
const byDomain: Record<string, number> = {}
const domains = new Set(state.controls.map(c => c.domain))
domains.forEach(domain => {
const domainControls = state.controls.filter(c => c.domain === domain)
const implemented = domainControls.filter(c => c.implementationStatus === 'IMPLEMENTED').length
byDomain[domain] = domainControls.length > 0
? Math.round((implemented / domainControls.length) * 100)
: 0
})
return {
overall,
byRegulation: byRegulation as Record<RegulationCode, number>,
byDomain: byDomain as Record<string, number>,
trend: 'STABLE', // Would need historical data to calculate
lastCalculated: new Date(),
}
}
private calculateEvidenceCoverage(): number {
const controls = this.getControls()
const implementedControls = controls.filter(c => c.implementationStatus === 'IMPLEMENTED')
if (implementedControls.length === 0) return 0
const controlsWithEvidence = implementedControls.filter(c => {
const evidence = this.getEvidenceByControlId(c.id)
return evidence.some(e => e.status === 'ACTIVE')
})
return Math.round((controlsWithEvidence.length / implementedControls.length) * 100)
}
// ---------------------------------------------------------------------------
// Risks
// ---------------------------------------------------------------------------
getRisks() {
return this.getState().risks
}
getRisksByStatus(status: string) {
return this.getRisks().filter(r => r.status === status)
}
getRisksBySeverity(severity: RiskSeverity) {
return this.getRisks().filter(r => r.severity === severity)
}
getCriticalRisks() {
return this.getRisks().filter(r => r.severity === 'CRITICAL' || r.severity === 'HIGH')
}
getAverageRiskScore(): number {
const risks = this.getRisks()
if (risks.length === 0) return 0
const totalScore = risks.reduce((sum, r) => sum + r.residualRiskScore, 0)
return Math.round(totalScore / risks.length)
}
}
export function createComplianceModule(
client: ComplianceClient,
getState: () => SDKState
): ComplianceModule {
return new ComplianceModule(client, getState)
}

View File

@@ -0,0 +1,155 @@
/**
* DSGVO Module
*
* GDPR compliance functionality
*/
import type {
DSRRequest,
DSRRequestType,
ConsentRecord,
ConsentPurpose,
ProcessingActivity,
DSFA,
TOM,
RetentionPolicy,
CookieBannerConfig,
SDKState,
} from '@breakpilot/compliance-sdk-types'
import { ComplianceClient } from '../client'
export class DSGVOModule {
private client: ComplianceClient
private getState: () => SDKState
constructor(client: ComplianceClient, getState: () => SDKState) {
this.client = client
this.getState = getState
}
// ---------------------------------------------------------------------------
// DSR (Data Subject Requests)
// ---------------------------------------------------------------------------
async submitDSR(type: DSRRequestType, requesterEmail: string, requesterName: string): Promise<DSRRequest> {
const response = await fetch(`${this.client.getTenantId()}/dsgvo/dsr`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type, requesterEmail, requesterName }),
})
return response.json()
}
getDSRRequests(): DSRRequest[] {
return this.getState().dsrRequests
}
getDSRById(id: string): DSRRequest | undefined {
return this.getState().dsrRequests.find(r => r.id === id)
}
// ---------------------------------------------------------------------------
// Consent Management
// ---------------------------------------------------------------------------
getConsents(): ConsentRecord[] {
return this.getState().consents
}
getConsentsByUserId(userId: string): ConsentRecord[] {
return this.getState().consents.filter(c => c.userId === userId)
}
hasConsent(userId: string, purpose: ConsentPurpose): boolean {
const consents = this.getConsentsByUserId(userId)
const latestConsent = consents
.filter(c => c.consentType === purpose)
.sort((a, b) => new Date(b.grantedAt).getTime() - new Date(a.grantedAt).getTime())[0]
return latestConsent?.granted && !latestConsent.revokedAt
}
// ---------------------------------------------------------------------------
// VVT (Processing Register)
// ---------------------------------------------------------------------------
getProcessingActivities(): ProcessingActivity[] {
return this.getState().vvt
}
getProcessingActivityById(id: string): ProcessingActivity | undefined {
return this.getState().vvt.find(p => p.id === id)
}
// ---------------------------------------------------------------------------
// DSFA
// ---------------------------------------------------------------------------
getDSFA(): DSFA | null {
return this.getState().dsfa
}
isDSFARequired(): boolean {
const state = this.getState()
const activeUseCase = state.useCases.find(uc => uc.id === state.activeUseCase)
return activeUseCase?.assessmentResult?.dsfaRequired ?? false
}
// ---------------------------------------------------------------------------
// TOMs
// ---------------------------------------------------------------------------
getTOMs(): TOM[] {
return this.getState().toms
}
getTOMsByCategory(category: string): TOM[] {
return this.getState().toms.filter(t => t.category === category)
}
getTOMScore(): number {
const toms = this.getTOMs()
if (toms.length === 0) return 0
const implemented = toms.filter(t => t.implementationStatus === 'IMPLEMENTED').length
return Math.round((implemented / toms.length) * 100)
}
// ---------------------------------------------------------------------------
// Retention Policies
// ---------------------------------------------------------------------------
getRetentionPolicies(): RetentionPolicy[] {
return this.getState().retentionPolicies
}
getUpcomingDeletions(days: number = 30): RetentionPolicy[] {
const cutoff = new Date()
cutoff.setDate(cutoff.getDate() + days)
return this.getState().retentionPolicies.filter(p => {
const nextReview = new Date(p.nextReviewDate)
return nextReview <= cutoff
})
}
// ---------------------------------------------------------------------------
// Cookie Banner
// ---------------------------------------------------------------------------
getCookieBannerConfig(): CookieBannerConfig | null {
return this.getState().cookieBanner
}
async generateCookieBannerCode(): Promise<{ html: string; css: string; js: string } | null> {
const config = this.getCookieBannerConfig()
if (!config) return null
const response = await this.client.generateDocument('cookie_banner', { config })
return response.content ? JSON.parse(response.content) : null
}
}
export function createDSGVOModule(client: ComplianceClient, getState: () => SDKState): DSGVOModule {
return new DSGVOModule(client, getState)
}

View File

@@ -0,0 +1,206 @@
/**
* RAG Module
*
* Legal RAG system for semantic search and AI-powered legal assistance
*/
import type {
SearchQuery,
SearchResponse,
AssistantQuery,
AssistantResponse,
LegalDocument,
ChatSession,
ChatMessage,
} from '@breakpilot/compliance-sdk-types'
import { ComplianceClient } from '../client'
export class RAGModule {
private client: ComplianceClient
private chatHistory: ChatMessage[] = []
private sessionId: string | null = null
constructor(client: ComplianceClient) {
this.client = client
}
// ---------------------------------------------------------------------------
// Search
// ---------------------------------------------------------------------------
async search(query: string, options?: Partial<SearchQuery>): Promise<SearchResponse> {
const searchRequest: SearchQuery = {
query,
limit: options?.limit ?? 10,
offset: options?.offset ?? 0,
filters: options?.filters,
includeMetadata: options?.includeMetadata ?? true,
scoreThreshold: options?.scoreThreshold ?? 0.5,
}
return this.client.searchRAG({
query: searchRequest.query,
filters: searchRequest.filters,
limit: searchRequest.limit,
offset: searchRequest.offset,
})
}
async searchByRegulation(regulation: string, query: string): Promise<SearchResponse> {
return this.search(query, {
filters: {
documentCodes: [regulation],
},
})
}
async searchByArticle(regulation: string, article: string): Promise<SearchResponse> {
return this.search(`${regulation} Artikel ${article}`, {
filters: {
documentCodes: [regulation],
articles: [article],
},
})
}
// ---------------------------------------------------------------------------
// Legal Assistant
// ---------------------------------------------------------------------------
async ask(question: string, options?: Partial<AssistantQuery>): Promise<AssistantResponse> {
const request: AssistantQuery = {
question,
context: options?.context,
documents: options?.documents,
maxSources: options?.maxSources ?? 5,
language: options?.language ?? 'de',
responseFormat: options?.responseFormat ?? 'detailed',
}
const response = await this.client.askRAG({
question: request.question,
context: request.context,
documents: request.documents,
maxSources: request.maxSources,
language: request.language,
})
// Add to chat history
this.chatHistory.push({
id: `user-${Date.now()}`,
role: 'user',
content: question,
timestamp: new Date(),
})
this.chatHistory.push({
id: `assistant-${Date.now()}`,
role: 'assistant',
content: response.answer,
timestamp: new Date(),
sources: response.sources,
})
return response
}
async askAboutRegulation(regulation: string, question: string): Promise<AssistantResponse> {
return this.ask(question, {
documents: [regulation],
context: `Kontext: Frage bezieht sich auf ${regulation}`,
})
}
async explainArticle(regulation: string, article: string): Promise<AssistantResponse> {
return this.ask(`Erkläre ${regulation} Artikel ${article} einfach und verständlich.`, {
documents: [regulation],
})
}
async checkCompliance(
regulation: string,
scenario: string
): Promise<AssistantResponse> {
return this.ask(
`Prüfe folgendes Szenario auf Compliance mit ${regulation}: ${scenario}`,
{
documents: [regulation],
responseFormat: 'detailed',
}
)
}
// ---------------------------------------------------------------------------
// Chat Session
// ---------------------------------------------------------------------------
startNewSession(): void {
this.sessionId = `session-${Date.now()}`
this.chatHistory = []
}
getChatHistory(): ChatMessage[] {
return [...this.chatHistory]
}
clearChatHistory(): void {
this.chatHistory = []
}
getSessionId(): string | null {
return this.sessionId
}
// ---------------------------------------------------------------------------
// Document Info
// ---------------------------------------------------------------------------
getAvailableRegulations(): readonly string[] {
return [
'DSGVO',
'AI_ACT',
'NIS2',
'EPRIVACY',
'TDDDG',
'SCC',
'DPF',
'CRA',
'EUCSA',
'DATA_ACT',
'DGA',
'DSA',
'EAA',
'BDSG',
'ISO_27001',
'BSI_GRUNDSCHUTZ',
'KRITIS',
'BAIT',
'VAIT',
'SOC2',
'PCI_DSS',
] as const
}
// ---------------------------------------------------------------------------
// Quick Actions
// ---------------------------------------------------------------------------
async getQuickAnswer(question: string): Promise<string> {
const response = await this.ask(question, {
responseFormat: 'concise',
maxSources: 3,
})
return response.answer
}
async findRelevantArticles(topic: string): Promise<SearchResponse> {
return this.search(topic, {
limit: 5,
scoreThreshold: 0.7,
})
}
}
export function createRAGModule(client: ComplianceClient): RAGModule {
return new RAGModule(client)
}

View File

@@ -0,0 +1,241 @@
/**
* Security Module
*
* Security scanning and SBOM management
*/
import type {
SBOM,
SecurityIssue,
SecurityScanResult,
BacklogItem,
SecurityIssueSeverity,
SecurityTool,
FindingsSummary,
SDKState,
} from '@breakpilot/compliance-sdk-types'
import { ComplianceClient } from '../client'
export class SecurityModule {
private client: ComplianceClient
private getState: () => SDKState
constructor(client: ComplianceClient, getState: () => SDKState) {
this.client = client
this.getState = getState
}
// ---------------------------------------------------------------------------
// Security Scanning
// ---------------------------------------------------------------------------
async startScan(options?: {
tools?: SecurityTool[]
targetPath?: string
severityThreshold?: SecurityIssueSeverity
generateSBOM?: boolean
}): Promise<{ id: string; status: string }> {
return this.client.startSecurityScan({
tools: options?.tools,
targetPath: options?.targetPath,
severityThreshold: options?.severityThreshold,
generateSBOM: options?.generateSBOM ?? true,
})
}
async getScanResult(scanId: string): Promise<SecurityScanResult | null> {
const result = await this.client.getSecurityScanResult(scanId)
return result as SecurityScanResult | null
}
getLastScanResult(): SecurityScanResult | null {
const screening = this.getState().screening
return screening?.securityScan ?? null
}
// ---------------------------------------------------------------------------
// SBOM
// ---------------------------------------------------------------------------
getSBOM(): SBOM | null {
return this.getState().sbom
}
getComponents() {
return this.getSBOM()?.components ?? []
}
getComponentsByLicense(license: string) {
return this.getComponents().filter(c => c.licenses.includes(license as never))
}
getVulnerableComponents() {
return this.getComponents().filter(c => c.vulnerabilities.length > 0)
}
getLicenseSummary(): Record<string, number> {
const components = this.getComponents()
const summary: Record<string, number> = {}
components.forEach(c => {
c.licenses.forEach(license => {
summary[license] = (summary[license] || 0) + 1
})
})
return summary
}
// ---------------------------------------------------------------------------
// Security Issues
// ---------------------------------------------------------------------------
getSecurityIssues(): SecurityIssue[] {
return this.getState().securityIssues
}
getIssueById(id: string): SecurityIssue | undefined {
return this.getSecurityIssues().find(i => i.id === id)
}
getIssuesBySeverity(severity: SecurityIssueSeverity): SecurityIssue[] {
return this.getSecurityIssues().filter(i => i.severity === severity)
}
getIssuesByStatus(status: string): SecurityIssue[] {
return this.getSecurityIssues().filter(i => i.status === status)
}
getIssuesByTool(tool: SecurityTool): SecurityIssue[] {
return this.getSecurityIssues().filter(i => i.tool === tool)
}
getOpenIssues(): SecurityIssue[] {
return this.getSecurityIssues().filter(i => i.status === 'OPEN' || i.status === 'IN_PROGRESS')
}
getCriticalIssues(): SecurityIssue[] {
return this.getSecurityIssues().filter(
i => (i.severity === 'CRITICAL' || i.severity === 'HIGH') && i.status === 'OPEN'
)
}
// ---------------------------------------------------------------------------
// Backlog
// ---------------------------------------------------------------------------
getBacklog(): BacklogItem[] {
return this.getState().securityBacklog
}
getBacklogByStatus(status: 'OPEN' | 'IN_PROGRESS' | 'DONE'): BacklogItem[] {
return this.getBacklog().filter(i => i.status === status)
}
getOverdueBacklogItems(): BacklogItem[] {
const now = new Date()
return this.getBacklog().filter(i => {
if (!i.dueDate || i.status === 'DONE') return false
return new Date(i.dueDate) < now
})
}
// ---------------------------------------------------------------------------
// Summary & Statistics
// ---------------------------------------------------------------------------
getSecuritySummary(): FindingsSummary {
const issues = this.getSecurityIssues()
const bySeverity: Record<SecurityIssueSeverity, number> = {
CRITICAL: 0,
HIGH: 0,
MEDIUM: 0,
LOW: 0,
INFO: 0,
}
const byStatus: Record<string, number> = {
OPEN: 0,
IN_PROGRESS: 0,
RESOLVED: 0,
ACCEPTED: 0,
FALSE_POSITIVE: 0,
}
const byTool: Record<string, number> = {}
issues.forEach(issue => {
bySeverity[issue.severity]++
byStatus[issue.status]++
byTool[issue.tool] = (byTool[issue.tool] || 0) + 1
})
// Calculate average resolution time for resolved issues
const resolvedIssues = issues.filter(i => i.status === 'RESOLVED' && i.resolvedAt)
let averageResolutionDays = 0
if (resolvedIssues.length > 0) {
const totalDays = resolvedIssues.reduce((sum, issue) => {
// Would need createdAt field to calculate properly
return sum + 7 // Placeholder
}, 0)
averageResolutionDays = Math.round(totalDays / resolvedIssues.length)
}
// Find oldest unresolved issue
const openIssues = issues.filter(i => i.status === 'OPEN')
let oldestUnresolvedDays = 0
// Would need createdAt field to calculate properly
return {
totalFindings: issues.length,
bySeverity,
byStatus: byStatus as Record<string, number>,
byTool: byTool as Record<SecurityTool, number>,
averageResolutionDays,
oldestUnresolvedDays,
}
}
getSecurityScore(): number {
const issues = this.getSecurityIssues()
const openIssues = issues.filter(i => i.status === 'OPEN' || i.status === 'IN_PROGRESS')
if (issues.length === 0) return 100
// Weight by severity
const severityWeights = {
CRITICAL: 10,
HIGH: 5,
MEDIUM: 2,
LOW: 1,
INFO: 0,
}
const totalWeight = issues.reduce((sum, i) => sum + severityWeights[i.severity], 0)
const openWeight = openIssues.reduce((sum, i) => sum + severityWeights[i.severity], 0)
if (totalWeight === 0) return 100
return Math.round(((totalWeight - openWeight) / totalWeight) * 100)
}
// ---------------------------------------------------------------------------
// Utilities
// ---------------------------------------------------------------------------
getAvailableTools(): SecurityTool[] {
return ['gitleaks', 'semgrep', 'bandit', 'trivy', 'grype', 'syft']
}
async exportSBOM(format: 'CycloneDX' | 'SPDX'): Promise<Blob> {
return this.client.exportState(format === 'CycloneDX' ? 'json' : 'json')
}
}
export function createSecurityModule(
client: ComplianceClient,
getState: () => SDKState
): SecurityModule {
return new SecurityModule(client, getState)
}