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,35 @@
#!/usr/bin/env node
/**
* BreakPilot Compliance SDK CLI
*
* Commands:
* - init: Initialize a new compliance project
* - deploy: Deploy to hardware (Mac Mini/Mac Studio)
* - scan: Run security scans
* - export: Export compliance reports
* - status: Check compliance status
*/
import { Command } from 'commander'
import { initCommand } from './commands/init'
import { deployCommand } from './commands/deploy'
import { scanCommand } from './commands/scan'
import { exportCommand } from './commands/export'
import { statusCommand } from './commands/status'
const program = new Command()
program
.name('breakpilot')
.description('BreakPilot Compliance SDK CLI')
.version('0.0.1')
// Register commands
program.addCommand(initCommand)
program.addCommand(deployCommand)
program.addCommand(scanCommand)
program.addCommand(exportCommand)
program.addCommand(statusCommand)
program.parse()

View File

@@ -0,0 +1,217 @@
/**
* Deploy command - Deploy to hardware (Mac Mini/Mac Studio)
*/
import { Command } from 'commander'
import * as fs from 'fs'
import * as path from 'path'
interface DeployOptions {
target?: string
config?: string
dryRun?: boolean
}
export const deployCommand = new Command('deploy')
.description('Deploy compliance services to hardware')
.option('-t, --target <target>', 'Deployment target (mac-mini, mac-studio, cloud)', 'mac-mini')
.option('-c, --config <path>', 'Path to config file', './breakpilot.config.json')
.option('--dry-run', 'Show what would be deployed without actually deploying', false)
.action(async (options: DeployOptions) => {
const chalk = (await import('chalk')).default
const ora = (await import('ora')).default
const inquirer = (await import('inquirer')).default
console.log(chalk.bold.blue('\n🚀 BreakPilot Compliance SDK - Deployment\n'))
// Check for config file
const configPath = path.resolve(options.config || './breakpilot.config.json')
if (!fs.existsSync(configPath)) {
console.log(chalk.yellow('⚠️ No config file found. Run `breakpilot init` first.'))
process.exit(1)
}
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'))
// Prompt for deployment details
const answers = await inquirer.prompt([
{
type: 'list',
name: 'target',
message: 'Select deployment target:',
choices: [
{ name: 'Mac Mini M4 Pro (64GB RAM, Qwen 2.5 32B)', value: 'mac-mini' },
{ name: 'Mac Studio M2 Ultra (512GB RAM, Qwen 2.5 40B)', value: 'mac-studio' },
{ name: 'Cloud (BreakPilot Servers)', value: 'cloud' },
],
default: options.target,
},
{
type: 'input',
name: 'hostname',
message: 'Target hostname/IP:',
when: (answers) => answers.target !== 'cloud',
default: 'localhost',
},
{
type: 'input',
name: 'sshUser',
message: 'SSH username:',
when: (answers) => answers.target !== 'cloud',
default: process.env.USER || 'admin',
},
{
type: 'confirm',
name: 'installLLM',
message: 'Install/update LLM model?',
when: (answers) => answers.target !== 'cloud',
default: true,
},
])
if (options.dryRun) {
console.log(chalk.yellow('\n📋 Dry run - no changes will be made\n'))
}
const spinner = ora('Preparing deployment...').start()
try {
// Generate docker-compose.yml
const dockerCompose = generateDockerCompose(answers.target, config)
if (options.dryRun) {
spinner.info('Would generate docker-compose.yml:')
console.log(chalk.gray(dockerCompose))
return
}
// For actual deployment, we'd:
// 1. SSH to target machine
// 2. Copy docker-compose.yml
// 3. Run docker-compose up -d
// 4. Install LLM if requested
spinner.text = 'Connecting to target...'
await sleep(1000) // Simulated
spinner.text = 'Deploying services...'
await sleep(2000) // Simulated
if (answers.installLLM) {
spinner.text = 'Installing LLM model (this may take a while)...'
await sleep(2000) // Simulated
}
spinner.succeed('Deployment complete!')
console.log(chalk.green('\n✅ Services deployed successfully'))
console.log(chalk.gray('\nDeployed services:'))
console.log(chalk.gray(' - API Gateway (port 443)'))
console.log(chalk.gray(' - Compliance Engine'))
console.log(chalk.gray(' - RAG Service'))
console.log(chalk.gray(' - Security Scanner'))
console.log(chalk.gray(' - PostgreSQL'))
console.log(chalk.gray(' - Qdrant'))
console.log(chalk.gray(' - MinIO'))
if (answers.installLLM) {
const model = answers.target === 'mac-studio' ? 'qwen2.5:40b' : 'qwen2.5:32b'
console.log(chalk.gray(` - Ollama (${model})`))
}
console.log(chalk.blue('\n🔗 Access your services at:'))
console.log(chalk.white(` https://${answers.hostname || 'localhost'}/api/v1`))
} catch (error) {
spinner.fail('Deployment failed')
console.error(chalk.red('Error:'), error)
process.exit(1)
}
})
function generateDockerCompose(target: string, config: Record<string, unknown>): string {
const llmModel = target === 'mac-studio' ? 'qwen2.5:40b' : 'qwen2.5:32b'
return `# Generated by BreakPilot CLI
# Target: ${target}
version: '3.8'
services:
api-gateway:
image: ghcr.io/breakpilot/compliance-sdk-gateway:latest
ports:
- "443:443"
- "80:80"
environment:
- DATABASE_URL=postgres://breakpilot:breakpilot@postgres:5432/compliance
- QDRANT_URL=http://qdrant:6333
- OLLAMA_URL=http://host.docker.internal:11434
- MINIO_URL=http://minio:9000
depends_on:
- postgres
- qdrant
- minio
restart: unless-stopped
compliance-engine:
image: ghcr.io/breakpilot/compliance-engine:latest
environment:
- DATABASE_URL=postgres://breakpilot:breakpilot@postgres:5432/compliance
depends_on:
- postgres
restart: unless-stopped
rag-service:
image: ghcr.io/breakpilot/rag-service:latest
environment:
- QDRANT_URL=http://qdrant:6333
- OLLAMA_URL=http://host.docker.internal:11434
- EMBEDDING_MODEL=bge-m3
depends_on:
- qdrant
restart: unless-stopped
security-scanner:
image: ghcr.io/breakpilot/security-scanner:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_USER=breakpilot
- POSTGRES_PASSWORD=breakpilot
- POSTGRES_DB=compliance
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
qdrant:
image: qdrant/qdrant:v1.12.1
volumes:
- qdrant_data:/qdrant/storage
restart: unless-stopped
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
- MINIO_ROOT_USER=breakpilot
- MINIO_ROOT_PASSWORD=breakpilot123
volumes:
- minio_data:/data
restart: unless-stopped
volumes:
postgres_data:
qdrant_data:
minio_data:
# Note: Ollama runs on the host system
# Install with: ollama pull ${llmModel}
`
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}

View File

@@ -0,0 +1,222 @@
/**
* Export command - Export compliance reports
*/
import { Command } from 'commander'
import * as fs from 'fs'
import * as path from 'path'
interface ExportOptions {
format?: string
output?: string
type?: string
}
export const exportCommand = new Command('export')
.description('Export compliance reports and documentation')
.option('-f, --format <format>', 'Export format (pdf, docx, json, csv)', 'pdf')
.option('-o, --output <path>', 'Output file path')
.option('-t, --type <type>', 'Report type (full, summary, vvt, tom, dsfa, controls, risks)', 'summary')
.action(async (options: ExportOptions) => {
const chalk = (await import('chalk')).default
const ora = (await import('ora')).default
const inquirer = (await import('inquirer')).default
console.log(chalk.bold.blue('\n📄 BreakPilot Compliance Export\n'))
// Prompt for export details
const answers = await inquirer.prompt([
{
type: 'list',
name: 'type',
message: 'Select report type:',
choices: [
{ name: 'Full Compliance Report', value: 'full' },
{ name: 'Executive Summary', value: 'summary' },
{ name: 'Verarbeitungsverzeichnis (VVT)', value: 'vvt' },
{ name: 'Technische & Organisatorische Maßnahmen (TOM)', value: 'tom' },
{ name: 'Datenschutz-Folgenabschätzung (DSFA)', value: 'dsfa' },
{ name: 'Controls Overview', value: 'controls' },
{ name: 'Risk Register', value: 'risks' },
{ name: 'SBOM (Software Bill of Materials)', value: 'sbom' },
],
default: options.type,
},
{
type: 'list',
name: 'format',
message: 'Select export format:',
choices: [
{ name: 'PDF', value: 'pdf' },
{ name: 'Word Document (DOCX)', value: 'docx' },
{ name: 'JSON', value: 'json' },
{ name: 'CSV', value: 'csv' },
{ name: 'CycloneDX (SBOM only)', value: 'cyclonedx' },
{ name: 'SPDX (SBOM only)', value: 'spdx' },
],
default: options.format,
},
{
type: 'input',
name: 'output',
message: 'Output file path:',
default: (answers: { type: string; format: string }) =>
`compliance-${answers.type}-${new Date().toISOString().split('T')[0]}.${answers.format}`,
},
])
const spinner = ora('Generating report...').start()
try {
// In a real implementation, this would:
// 1. Connect to the compliance API
// 2. Fetch all relevant data
// 3. Generate the report in the requested format
spinner.text = 'Fetching compliance data...'
await sleep(1000)
spinner.text = 'Generating document...'
await sleep(1500)
const outputPath = path.resolve(answers.output)
// Generate mock output
const content = generateMockReport(answers.type, answers.format)
fs.writeFileSync(outputPath, content)
spinner.succeed('Report generated successfully!')
console.log(chalk.green('\n✅ Export complete'))
console.log(chalk.gray(` File: ${outputPath}`))
console.log(chalk.gray(` Type: ${answers.type}`))
console.log(chalk.gray(` Format: ${answers.format}`))
// Show report preview for JSON
if (answers.format === 'json') {
console.log(chalk.bold('\n📋 Preview:\n'))
const preview = JSON.parse(content)
console.log(chalk.gray(JSON.stringify(preview, null, 2).substring(0, 500) + '...'))
}
} catch (error) {
spinner.fail('Export failed')
console.error(chalk.red('Error:'), error)
process.exit(1)
}
})
function generateMockReport(type: string, format: string): string {
const reportData = {
generatedAt: new Date().toISOString(),
reportType: type,
format: format,
organization: 'Example Organization',
complianceScore: 78,
summary: {
totalControls: 44,
implementedControls: 35,
partialControls: 6,
openControls: 3,
totalRisks: 12,
criticalRisks: 1,
highRisks: 2,
regulations: ['DSGVO', 'NIS2', 'AI Act'],
},
sections: getSectionsForType(type),
}
if (format === 'json' || format === 'cyclonedx' || format === 'spdx') {
return JSON.stringify(reportData, null, 2)
}
// For PDF/DOCX, we'd use a proper document generation library
// For now, return a placeholder
return `[${format.toUpperCase()} Report - ${type}]\n\n${JSON.stringify(reportData, null, 2)}`
}
function getSectionsForType(type: string): Record<string, unknown>[] {
switch (type) {
case 'vvt':
return [
{
id: 'vvt-1',
name: 'Kundenmanagement',
purpose: 'Verwaltung von Kundenbeziehungen',
legalBasis: 'Art. 6 Abs. 1 lit. b DSGVO',
dataCategories: ['Kontaktdaten', 'Vertragsdetails', 'Kommunikationshistorie'],
retentionPeriod: '10 Jahre nach Vertragsende',
},
{
id: 'vvt-2',
name: 'Personalverwaltung',
purpose: 'Verwaltung von Mitarbeiterdaten',
legalBasis: 'Art. 6 Abs. 1 lit. b, c DSGVO',
dataCategories: ['Personaldaten', 'Gehaltsdaten', 'Leistungsdaten'],
retentionPeriod: '10 Jahre nach Beendigung',
},
]
case 'tom':
return [
{
category: 'Zutrittskontrolle',
measures: [
'Zutrittskontrollsystem mit Chipkarten',
'Videoüberwachung der Eingänge',
'Besucherregistrierung',
],
},
{
category: 'Zugangskontrolle',
measures: [
'Passwort-Policy (min. 12 Zeichen)',
'Multi-Faktor-Authentifizierung',
'Automatische Sperrung nach 5 Fehlversuchen',
],
},
]
case 'controls':
return [
{
id: 'ctrl-1',
domain: 'ACCESS_CONTROL',
title: 'Benutzerauthentifizierung',
status: 'IMPLEMENTED',
evidence: ['auth-policy.pdf', 'mfa-config.png'],
},
{
id: 'ctrl-2',
domain: 'DATA_PROTECTION',
title: 'Datenverschlüsselung',
status: 'IMPLEMENTED',
evidence: ['encryption-certificate.pdf'],
},
]
case 'risks':
return [
{
id: 'risk-1',
title: 'Datenverlust durch Cyberangriff',
likelihood: 3,
impact: 5,
severity: 'HIGH',
mitigation: 'Backup-Strategie, Incident Response Plan',
status: 'MITIGATED',
},
{
id: 'risk-2',
title: 'DSGVO-Bußgeld wegen unzureichender Dokumentation',
likelihood: 2,
impact: 4,
severity: 'MEDIUM',
mitigation: 'Regelmäßige Dokumentationsaudits',
status: 'MONITORING',
},
]
default:
return []
}
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}

View File

@@ -0,0 +1,221 @@
/**
* Init command - Initialize a new compliance project
*/
import { Command } from 'commander'
import * as fs from 'fs'
import * as path from 'path'
interface InitOptions {
template?: string
force?: boolean
}
export const initCommand = new Command('init')
.description('Initialize a new compliance project')
.argument('[directory]', 'Directory to initialize', '.')
.option('-t, --template <template>', 'Project template (react, vue, vanilla)', 'react')
.option('-f, --force', 'Overwrite existing files', false)
.action(async (directory: string, options: InitOptions) => {
const chalk = (await import('chalk')).default
const ora = (await import('ora')).default
const inquirer = (await import('inquirer')).default
console.log(chalk.bold.blue('\n🚀 BreakPilot Compliance SDK - Project Setup\n'))
// Prompt for configuration
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'Project name:',
default: path.basename(path.resolve(directory)),
},
{
type: 'list',
name: 'template',
message: 'Select a template:',
choices: [
{ name: 'React (Recommended)', value: 'react' },
{ name: 'Vue 3', value: 'vue' },
{ name: 'Vanilla JS', value: 'vanilla' },
],
default: options.template,
},
{
type: 'input',
name: 'apiEndpoint',
message: 'API Endpoint:',
default: 'https://compliance.breakpilot.app/api/v1',
},
{
type: 'confirm',
name: 'includeComponents',
message: 'Include pre-built UI components?',
default: true,
},
])
const spinner = ora('Setting up project...').start()
try {
const targetDir = path.resolve(directory)
// Create directory if it doesn't exist
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true })
}
// Create config file
const configPath = path.join(targetDir, 'breakpilot.config.json')
const config = {
projectName: answers.projectName,
template: answers.template,
apiEndpoint: answers.apiEndpoint,
version: '0.0.1',
features: {
dsgvo: true,
compliance: true,
rag: true,
security: true,
},
}
fs.writeFileSync(configPath, JSON.stringify(config, null, 2))
// Create .env.example
const envExamplePath = path.join(targetDir, '.env.example')
const envContent = `# BreakPilot Compliance SDK Configuration
BREAKPILOT_API_ENDPOINT=${answers.apiEndpoint}
BREAKPILOT_API_KEY=pk_live_xxx
BREAKPILOT_TENANT_ID=your_tenant_id
`
fs.writeFileSync(envExamplePath, envContent)
// Create example usage file based on template
const examplePath = path.join(targetDir, `compliance-example.${getExtension(answers.template)}`)
fs.writeFileSync(examplePath, getExampleCode(answers.template, answers.apiEndpoint))
spinner.succeed('Project initialized successfully!')
console.log(chalk.green('\n✅ Project created at:'), chalk.white(targetDir))
console.log(chalk.gray('\nNext steps:'))
console.log(chalk.gray(' 1. Copy .env.example to .env and fill in your API key'))
console.log(chalk.gray(` 2. Install the SDK: npm install @breakpilot/compliance-sdk-${answers.template}`))
console.log(chalk.gray(' 3. Import and use the SDK in your application'))
console.log(chalk.gray('\nDocumentation: https://docs.breakpilot.app/sdk'))
} catch (error) {
spinner.fail('Failed to initialize project')
console.error(chalk.red('Error:'), error)
process.exit(1)
}
})
function getExtension(template: string): string {
switch (template) {
case 'react':
return 'tsx'
case 'vue':
return 'vue'
default:
return 'js'
}
}
function getExampleCode(template: string, apiEndpoint: string): string {
switch (template) {
case 'react':
return `// Example React integration
import {
ComplianceProvider,
ConsentBanner,
DSRPortal,
useCompliance
} from '@breakpilot/compliance-sdk-react';
function App() {
return (
<ComplianceProvider
apiEndpoint="${apiEndpoint}"
apiKey={process.env.BREAKPILOT_API_KEY}
tenantId={process.env.BREAKPILOT_TENANT_ID}
>
<ConsentBanner position="BOTTOM" theme="LIGHT" />
<MyApp />
</ComplianceProvider>
);
}
function MyApp() {
const { state, compliance, rag } = useCompliance();
const askQuestion = async () => {
const answer = await rag.ask('Was ist bei Art. 9 DSGVO zu beachten?');
console.log(answer);
};
return (
<div>
<h1>Compliance Score: {compliance.calculateComplianceScore().overall}%</h1>
<button onClick={askQuestion}>Frage stellen</button>
</div>
);
}
export default App;
`
case 'vue':
return `<!-- Example Vue 3 integration -->
<script setup lang="ts">
import { useCompliance, useRAG } from '@breakpilot/compliance-sdk-vue';
const { state, complianceScore } = useCompliance();
const { ask, chatHistory, isLoading } = useRAG();
const askQuestion = async () => {
await ask('Was ist bei Art. 9 DSGVO zu beachten?');
};
</script>
<template>
<div>
<h1>Compliance Score: {{ complianceScore }}%</h1>
<button @click="askQuestion" :disabled="isLoading">
{{ isLoading ? 'Lädt...' : 'Frage stellen' }}
</button>
<div v-for="msg in chatHistory" :key="msg.id">
<strong>{{ msg.role }}:</strong> {{ msg.content }}
</div>
</div>
</template>
`
default:
return `// Example Vanilla JS integration
import { BreakPilotSDK } from '@breakpilot/compliance-sdk-vanilla';
BreakPilotSDK.init({
apiEndpoint: '${apiEndpoint}',
apiKey: 'pk_live_xxx',
autoInjectBanner: true,
bannerConfig: {
position: 'BOTTOM',
theme: 'LIGHT',
language: 'de'
},
onConsentChange: (consents) => {
console.log('Consents updated:', consents);
if (consents.ANALYTICS) {
// Load analytics
}
},
onReady: () => {
console.log('SDK ready!');
}
});
// Or use Web Components:
// <breakpilot-consent-banner api-key="pk_live_xxx" theme="light" position="bottom">
// </breakpilot-consent-banner>
`
}
}

View File

@@ -0,0 +1,228 @@
/**
* Scan command - Run security scans
*/
import { Command } from 'commander'
import * as path from 'path'
interface ScanOptions {
tools?: string
output?: string
format?: string
severity?: string
}
export const scanCommand = new Command('scan')
.description('Run security scans on your codebase')
.argument('[path]', 'Path to scan', '.')
.option('-t, --tools <tools>', 'Comma-separated list of tools (gitleaks,semgrep,bandit,trivy,grype,syft)', 'all')
.option('-o, --output <path>', 'Output file path')
.option('-f, --format <format>', 'Output format (json, sarif, table)', 'table')
.option('-s, --severity <level>', 'Minimum severity to report (low, medium, high, critical)', 'low')
.action(async (scanPath: string, options: ScanOptions) => {
const chalk = (await import('chalk')).default
const ora = (await import('ora')).default
console.log(chalk.bold.blue('\n🔒 BreakPilot Security Scanner\n'))
const targetPath = path.resolve(scanPath)
console.log(chalk.gray(`Scanning: ${targetPath}\n`))
const tools = options.tools === 'all'
? ['gitleaks', 'semgrep', 'bandit', 'trivy', 'grype', 'syft']
: options.tools!.split(',').map(t => t.trim())
const results: ScanResult[] = []
for (const tool of tools) {
const spinner = ora(`Running ${tool}...`).start()
try {
// Simulate running the tool
await sleep(1500)
const toolResult = simulateToolResult(tool)
results.push(toolResult)
if (toolResult.findings.length > 0) {
spinner.warn(`${tool}: ${toolResult.findings.length} findings`)
} else {
spinner.succeed(`${tool}: No issues found`)
}
} catch (error) {
spinner.fail(`${tool}: Failed`)
}
}
// Summary
console.log(chalk.bold('\n📊 Scan Summary\n'))
const allFindings = results.flatMap(r => r.findings)
const bySeverity = {
critical: allFindings.filter(f => f.severity === 'CRITICAL'),
high: allFindings.filter(f => f.severity === 'HIGH'),
medium: allFindings.filter(f => f.severity === 'MEDIUM'),
low: allFindings.filter(f => f.severity === 'LOW'),
}
if (bySeverity.critical.length > 0) {
console.log(chalk.red(` 🔴 Critical: ${bySeverity.critical.length}`))
}
if (bySeverity.high.length > 0) {
console.log(chalk.red(` 🟠 High: ${bySeverity.high.length}`))
}
if (bySeverity.medium.length > 0) {
console.log(chalk.yellow(` 🟡 Medium: ${bySeverity.medium.length}`))
}
if (bySeverity.low.length > 0) {
console.log(chalk.gray(` 🟢 Low: ${bySeverity.low.length}`))
}
if (allFindings.length === 0) {
console.log(chalk.green(' ✅ No security issues found!'))
} else {
console.log(chalk.gray(`\n Total: ${allFindings.length} findings`))
// Show top findings
if (options.format === 'table') {
console.log(chalk.bold('\n📋 Top Findings\n'))
const topFindings = allFindings
.sort((a, b) => severityOrder(b.severity) - severityOrder(a.severity))
.slice(0, 10)
for (const finding of topFindings) {
const severityColor = getSeverityColor(finding.severity)
console.log(
` ${severityColor(finding.severity.padEnd(8))} ` +
`${chalk.gray(finding.tool.padEnd(10))} ` +
`${finding.title}`
)
if (finding.file) {
console.log(chalk.gray(` └─ ${finding.file}:${finding.line || '?'}`))
}
}
if (allFindings.length > 10) {
console.log(chalk.gray(`\n ... and ${allFindings.length - 10} more findings`))
}
}
}
// Write output if requested
if (options.output) {
const fs = await import('fs')
const output = {
scanDate: new Date().toISOString(),
targetPath,
tools,
summary: {
total: allFindings.length,
critical: bySeverity.critical.length,
high: bySeverity.high.length,
medium: bySeverity.medium.length,
low: bySeverity.low.length,
},
findings: allFindings,
}
fs.writeFileSync(options.output, JSON.stringify(output, null, 2))
console.log(chalk.gray(`\nResults written to: ${options.output}`))
}
// Exit with error if critical findings
if (bySeverity.critical.length > 0 || bySeverity.high.length > 0) {
process.exit(1)
}
})
interface Finding {
id: string
tool: string
severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW'
title: string
description?: string
file?: string
line?: number
recommendation?: string
}
interface ScanResult {
tool: string
findings: Finding[]
}
function simulateToolResult(tool: string): ScanResult {
// Simulate some findings for demonstration
const findings: Finding[] = []
switch (tool) {
case 'gitleaks':
// Secrets detection - usually finds nothing in clean repos
break
case 'semgrep':
findings.push({
id: 'semgrep-1',
tool: 'semgrep',
severity: 'MEDIUM',
title: 'Potential SQL injection',
description: 'User input used in SQL query without parameterization',
file: 'src/db/queries.ts',
line: 42,
recommendation: 'Use parameterized queries instead of string concatenation',
})
break
case 'bandit':
// Python security - skip if not a Python project
break
case 'trivy':
findings.push({
id: 'trivy-1',
tool: 'trivy',
severity: 'HIGH',
title: 'CVE-2024-1234 in lodash@4.17.20',
description: 'Prototype pollution vulnerability',
recommendation: 'Upgrade to lodash@4.17.21 or higher',
})
break
case 'grype':
findings.push({
id: 'grype-1',
tool: 'grype',
severity: 'LOW',
title: 'Outdated dependency: axios@0.21.0',
recommendation: 'Update to latest version',
})
break
case 'syft':
// SBOM generation - no findings, just metadata
break
}
return { tool, findings }
}
function severityOrder(severity: string): number {
switch (severity) {
case 'CRITICAL': return 4
case 'HIGH': return 3
case 'MEDIUM': return 2
case 'LOW': return 1
default: return 0
}
}
function getSeverityColor(severity: string): (text: string) => string {
const chalk = require('chalk')
switch (severity) {
case 'CRITICAL': return chalk.red.bold
case 'HIGH': return chalk.red
case 'MEDIUM': return chalk.yellow
case 'LOW': return chalk.gray
default: return chalk.white
}
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}

View File

@@ -0,0 +1,161 @@
/**
* Status command - Check compliance status
*/
import { Command } from 'commander'
interface StatusOptions {
json?: boolean
verbose?: boolean
}
export const statusCommand = new Command('status')
.description('Check current compliance status')
.option('-j, --json', 'Output as JSON', false)
.option('-v, --verbose', 'Show detailed status', false)
.action(async (options: StatusOptions) => {
const chalk = (await import('chalk')).default
const ora = (await import('ora')).default
if (!options.json) {
console.log(chalk.bold.blue('\n📊 BreakPilot Compliance Status\n'))
}
const spinner = options.json ? null : ora('Fetching status...').start()
try {
// Simulate fetching status from API
await sleep(1000)
const status = {
lastUpdated: new Date().toISOString(),
overallScore: 78,
trend: 'UP',
regulations: {
DSGVO: { score: 85, status: 'COMPLIANT' },
NIS2: { score: 72, status: 'PARTIAL' },
'AI Act': { score: 65, status: 'IN_PROGRESS' },
},
controls: {
total: 44,
implemented: 35,
partial: 6,
notImplemented: 3,
},
risks: {
total: 12,
critical: 1,
high: 2,
medium: 5,
low: 4,
},
evidence: {
total: 28,
valid: 24,
expiring: 3,
expired: 1,
},
dsrRequests: {
pending: 2,
inProgress: 1,
completed: 15,
},
nextActions: [
{
priority: 'HIGH',
action: 'Address critical risk: Data breach potential',
dueDate: '2024-02-15',
},
{
priority: 'MEDIUM',
action: 'Update expired evidence: Security audit report',
dueDate: '2024-02-20',
},
{
priority: 'MEDIUM',
action: 'Complete NIS2 gap assessment',
dueDate: '2024-03-01',
},
],
}
if (options.json) {
console.log(JSON.stringify(status, null, 2))
return
}
spinner?.succeed('Status retrieved')
// Overall Score
const scoreColor = status.overallScore >= 80 ? chalk.green :
status.overallScore >= 60 ? chalk.yellow : chalk.red
const trendIcon = status.trend === 'UP' ? '↑' :
status.trend === 'DOWN' ? '↓' : '→'
console.log(chalk.bold('\n🎯 Overall Compliance Score'))
console.log(` ${scoreColor.bold(status.overallScore + '%')} ${chalk.gray(trendIcon)}`)
// Regulations
console.log(chalk.bold('\n📜 Regulations'))
Object.entries(status.regulations).forEach(([reg, data]) => {
const color = data.score >= 80 ? chalk.green :
data.score >= 60 ? chalk.yellow : chalk.red
const statusIcon = data.status === 'COMPLIANT' ? '✓' :
data.status === 'PARTIAL' ? '◐' : '○'
console.log(` ${statusIcon} ${reg.padEnd(12)} ${color(data.score + '%')} ${chalk.gray(data.status)}`)
})
// Controls
console.log(chalk.bold('\n🔧 Controls'))
console.log(` ${chalk.green('●')} Implemented: ${status.controls.implemented}`)
console.log(` ${chalk.yellow('●')} Partial: ${status.controls.partial}`)
console.log(` ${chalk.red('●')} Not Implemented: ${status.controls.notImplemented}`)
console.log(chalk.gray(` Total: ${status.controls.total}`))
// Risks
console.log(chalk.bold('\n⚠ Risks'))
if (status.risks.critical > 0) {
console.log(` ${chalk.red.bold('🔴')} Critical: ${status.risks.critical}`)
}
if (status.risks.high > 0) {
console.log(` ${chalk.red('🟠')} High: ${status.risks.high}`)
}
console.log(` ${chalk.yellow('🟡')} Medium: ${status.risks.medium}`)
console.log(` ${chalk.gray('🟢')} Low: ${status.risks.low}`)
// Evidence
if (options.verbose) {
console.log(chalk.bold('\n📎 Evidence'))
console.log(` ${chalk.green('●')} Valid: ${status.evidence.valid}`)
console.log(` ${chalk.yellow('●')} Expiring: ${status.evidence.expiring}`)
console.log(` ${chalk.red('●')} Expired: ${status.evidence.expired}`)
}
// DSR Requests
if (options.verbose) {
console.log(chalk.bold('\n📬 DSR Requests'))
console.log(` Pending: ${status.dsrRequests.pending}`)
console.log(` In Progress: ${status.dsrRequests.inProgress}`)
console.log(` Completed: ${status.dsrRequests.completed}`)
}
// Next Actions
console.log(chalk.bold('\n📋 Next Actions'))
status.nextActions.forEach(action => {
const priorityColor = action.priority === 'HIGH' ? chalk.red :
action.priority === 'MEDIUM' ? chalk.yellow : chalk.gray
console.log(` ${priorityColor('●')} ${action.action}`)
console.log(chalk.gray(` Due: ${action.dueDate}`))
})
console.log('')
} catch (error) {
spinner?.fail('Failed to fetch status')
console.error(chalk.red('Error:'), error)
process.exit(1)
}
})
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}

View File

@@ -0,0 +1,18 @@
/**
* @breakpilot/compliance-sdk-cli
*
* CLI tool for BreakPilot Compliance SDK
*
* Commands:
* - init: Initialize a new compliance project
* - deploy: Deploy to hardware (Mac Mini/Mac Studio)
* - scan: Run security scans
* - export: Export compliance reports
* - status: Check compliance status
*/
export { initCommand } from './commands/init'
export { deployCommand } from './commands/deploy'
export { scanCommand } from './commands/scan'
export { exportCommand } from './commands/export'
export { statusCommand } from './commands/status'