fix(sdk): Fix ScopeDecisionTab crash — type mismatches with backend types
Some checks failed
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 38s
CI/CD / test-python-backend-compliance (push) Successful in 37s
CI/CD / test-python-document-crawler (push) Successful in 24s
CI/CD / test-python-dsms-gateway (push) Successful in 20s
CI/CD / deploy-hetzner (push) Failing after 5s

- DEPTH_LEVEL_COLORS: simple strings → objects with {bg, border, badge, text} Tailwind classes
- decision.reasoning: render as mapped array instead of direct JSX child
- trigger.X → trigger.rule.X for TriggeredHardTrigger properties
- doc.isMandatory → doc.required, doc.depthDescription → doc.depth
- doc.effortEstimate → doc.estimatedEffort, doc.triggeredByHardTrigger → doc.triggeredBy
- decision.gapAnalysis → decision.gaps (matching ScopeDecision type)
- getSeverityBadge: uppercase severity ('LOW'|'MEDIUM'|'HIGH'|'CRITICAL')
- Also includes CLAUDE.md and DEVELOPER.md CI/CD documentation updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-11 09:07:41 +01:00
parent a673cb0ce4
commit 46048554cb
4 changed files with 137 additions and 80 deletions

View File

@@ -2,41 +2,69 @@
## Entwicklungsumgebung (WICHTIG - IMMER ZUERST LESEN)
### Zwei-Rechner-Setup
### Zwei-Rechner-Setup + Hetzner
| Geraet | Rolle | Aufgaben |
|--------|-------|----------|
| **MacBook** | Entwicklung | Claude Terminal, Code-Entwicklung, Browser (Frontend-Tests) |
| **Mac Mini** | Server | Docker, alle Services, Tests, Builds, Deployment |
| **Mac Mini** | Lokaler Server | Docker fuer lokale Dev/Tests (NICHT mehr fuer Production!) |
| **Hetzner** | Production | CI/CD Build + Deploy via Gitea Actions |
**WICHTIG:** Code wird direkt auf dem MacBook in diesem Repo bearbeitet. Docker und Services laufen auf dem Mac Mini.
**WICHTIG:** Code wird auf dem MacBook bearbeitet. Production-Deployment laeuft automatisch auf Hetzner via CI/CD.
### Entwicklungsworkflow
### Entwicklungsworkflow (CI/CD — seit 2026-03-11)
```bash
# 1. Code auf MacBook bearbeiten (dieses Verzeichnis)
# 2. Committen und pushen:
# 2. Committen und zu BEIDEN Remotes pushen:
git push origin main && git push gitea main
# 3. Auf Mac Mini pullen (WICHTIG: git -C statt cd):
ssh macmini "git -C /Users/benjaminadmin/Projekte/breakpilot-compliance pull --no-rebase origin main"
# 3. FERTIG! Gitea Actions auf Hetzner uebernimmt automatisch:
# Push auf main → Lint → Tests → Build → Deploy
# Pipeline: .gitea/workflows/ci.yaml
# Dauer: ca. 3 Minuten
# Status pruefen: https://gitea.meghsakha.com/Benjamin_Boenisch/breakpilot-compliance/actions
```
# 4. Container neu bauen (WICHTIG: -f statt cd, da cd in SSH nicht funktioniert!):
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml build --no-cache <service> && /usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml up -d <service>"
**NICHT MEHR NOETIG:** Manuelles `ssh macmini "docker compose build"` — das macht jetzt die CI/CD Pipeline!
### CI/CD Pipeline (Gitea Actions → Hetzner)
```
Push auf main → go-lint/python-lint/nodejs-lint (nur PRs)
→ test-go-ai-compliance
→ test-python-backend-compliance
→ test-python-document-crawler
→ test-python-dsms-gateway
→ deploy-hetzner (nur wenn ALLE Tests gruen)
```
**Dateien:**
- `.gitea/workflows/ci.yaml` — Pipeline-Definition
- `docker-compose.hetzner.yml` — Override: arm64→amd64 fuer Hetzner (x86_64)
- Deploy-Pfad auf Hetzner: `/opt/breakpilot-compliance/`
**Ablauf deploy-hetzner:**
1. `git pull` im Deploy-Dir
2. `docker compose -f docker-compose.yml -f docker-compose.hetzner.yml build --parallel`
3. `docker compose up -d --remove-orphans`
4. Health Checks
### Lokale Entwicklung (Mac Mini — optional)
```bash
# Nur fuer lokale Tests, NICHT fuer Production:
ssh macmini "git -C /Users/benjaminadmin/Projekte/breakpilot-compliance pull --no-rebase origin main"
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml build --no-cache <service>"
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml up -d <service>"
# Fuer schnelle Iteration ohne Commit (rsync):
rsync -avz --exclude node_modules --exclude .next --exclude .git \
admin-compliance/ macmini:~/Projekte/breakpilot-compliance/admin-compliance/
```
### SSH-Verbindung (fuer Docker/Tests)
```bash
# RICHTIG — cd funktioniert NICHT in SSH-Einzelbefehlen:
ssh macmini "git -C /Users/benjaminadmin/Projekte/breakpilot-compliance <git-cmd>"
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml <compose-cmd>"
ssh macmini "/usr/local/bin/docker exec bp-compliance-<service> <cmd>"
```
**WICHTIG:** Docker-Pfad auf Mac Mini ist `/usr/local/bin/docker` (nicht im Standard-SSH-PATH).
**WICHTIG:** `cd` funktioniert NICHT in SSH-Einzelbefehlen — immer `-f <pfad>/docker-compose.yml` verwenden!
---
@@ -59,21 +87,25 @@ Pruefen: `curl -sf http://macmini:8099/health`
---
## Haupt-URLs (Browser auf MacBook)
## Haupt-URLs
### Frontends
### Production (Hetzner — primaer)
| URL | Service | Beschreibung |
|-----|---------|--------------|
| **https://macmini:3007/** | Admin Compliance | SDK-Dashboard, alle Compliance-Module |
| **https://macmini:3006/** | Developer Portal | API-Dokumentation fuer Kunden |
| **https://admin-dev.breakpilot.ai/** | Admin Compliance | SDK-Dashboard, alle Compliance-Module |
| **https://developers-dev.breakpilot.ai/** | Developer Portal | API-Dokumentation fuer Kunden |
| https://api-dev.breakpilot.ai/ | Backend Compliance | Compliance APIs (DSGVO, DSR, GDPR) |
| https://sdk-dev.breakpilot.ai/ | AI Compliance SDK | KI-konforme Compliance-Analyse |
### Backend-APIs
### Lokal (Mac Mini — nur Dev/Tests)
| URL | Service | Beschreibung |
|-----|---------|--------------|
| https://macmini:8002/ | Backend Compliance | Compliance APIs (DSGVO, DSR, GDPR) |
| https://macmini:8093/ | AI Compliance SDK | KI-konforme Compliance-Analyse |
| https://macmini:3007/ | Admin Compliance | Lokale Entwicklung |
| https://macmini:3006/ | Developer Portal | Lokale Entwicklung |
| https://macmini:8002/ | Backend Compliance | Lokale Entwicklung |
| https://macmini:8093/ | AI Compliance SDK | Lokale Entwicklung |
### Admin Compliance Module (https://macmini:3007/)
@@ -169,50 +201,54 @@ breakpilot-compliance/
├── dsms-node/ # IPFS Node
├── dsms-gateway/ # IPFS Gateway
├── scripts/ # Helper Scripts
── docker-compose.yml # Compliance Compose (~8 Services)
── docker-compose.yml # Compliance Compose (~10 Services, platform: arm64)
├── docker-compose.hetzner.yml # Override: arm64→amd64 fuer Hetzner
└── .gitea/workflows/ci.yaml # CI/CD Pipeline (Lint → Tests → Deploy)
```
---
## Haeufige Befehle
### Docker
### Deployment (CI/CD — Standardweg)
```bash
# Compliance-Services starten (Core muss laufen!)
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml up -d"
# Committen und pushen → CI/CD deployt automatisch auf Hetzner:
git push origin main && git push gitea main
# Einzelnen Service neu bauen
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml build --no-cache <service>"
# CI-Status pruefen (im Browser):
# https://gitea.meghsakha.com/Benjamin_Boenisch/breakpilot-compliance/actions
# Service neu bauen und starten
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml build --no-cache <service> && /usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml up -d <service>"
# Logs
ssh macmini "/usr/local/bin/docker logs -f bp-compliance-<service>"
# Status
ssh macmini "/usr/local/bin/docker ps --filter name=bp-compliance"
# Health Checks:
curl -sf https://api-dev.breakpilot.ai/health
curl -sf https://sdk-dev.breakpilot.ai/health
```
**WICHTIG:** Docker-Pfad auf Mac Mini ist `/usr/local/bin/docker` (nicht im Standard-SSH-PATH).
**WICHTIG:** `cd` funktioniert NICHT in SSH-Einzelbefehlen — immer `-f <pfad>/docker-compose.yml` verwenden!
Der CLAUDE.md-Entwicklungsworkflow und die Beispiele mit `cd ... &&` sind veraltet — nie so verwenden.
### Git
```bash
# Zu BEIDEN Remotes pushen (PFLICHT! — vom MacBook):
git push origin main && git push gitea main
# Auf Mac Mini pullen (RICHTIG: git -C statt cd):
ssh macmini "git -C /Users/benjaminadmin/Projekte/breakpilot-compliance pull --no-rebase origin main"
# Remotes:
# origin: lokale Gitea (macmini:3003)
# gitea: gitea.meghsakha.com:22222
```
### Lokale Docker-Befehle (Mac Mini — nur fuer Dev/Tests)
```bash
# Logs
ssh macmini "/usr/local/bin/docker logs -f bp-compliance-<service>"
# Status
ssh macmini "/usr/local/bin/docker ps --filter name=bp-compliance"
# Lokaler Rebuild (nur wenn noetig):
ssh macmini "git -C /Users/benjaminadmin/Projekte/breakpilot-compliance pull --no-rebase origin main"
ssh macmini "/usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml build --no-cache <service> && /usr/local/bin/docker compose -f /Users/benjaminadmin/Projekte/breakpilot-compliance/docker-compose.yml up -d <service>"
```
---
## Kernprinzipien

View File

@@ -58,18 +58,18 @@ export function ScopeDecisionTab({
return 'from-green-500 to-green-600'
}
const getSeverityBadge = (severity: 'low' | 'medium' | 'high' | 'critical') => {
const getSeverityBadge = (severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL') => {
const colors = {
low: 'bg-gray-100 text-gray-800',
medium: 'bg-yellow-100 text-yellow-800',
high: 'bg-orange-100 text-orange-800',
critical: 'bg-red-100 text-red-800',
LOW: 'bg-gray-100 text-gray-800',
MEDIUM: 'bg-yellow-100 text-yellow-800',
HIGH: 'bg-orange-100 text-orange-800',
CRITICAL: 'bg-red-100 text-red-800',
}
const labels = {
low: 'Niedrig',
medium: 'Mittel',
high: 'Hoch',
critical: 'Kritisch',
LOW: 'Niedrig',
MEDIUM: 'Mittel',
HIGH: 'Hoch',
CRITICAL: 'Kritisch',
}
return (
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${colors[severity]}`}>
@@ -111,8 +111,8 @@ export function ScopeDecisionTab({
{DEPTH_LEVEL_LABELS[decision.determinedLevel]}
</h2>
<p className="text-gray-700 mb-3">{DEPTH_LEVEL_DESCRIPTIONS[decision.determinedLevel]}</p>
{decision.reasoning && (
<p className="text-sm text-gray-600 italic">{decision.reasoning}</p>
{decision.reasoning && decision.reasoning.length > 0 && (
<p className="text-sm text-gray-600 italic">{decision.reasoning.map(r => r.description).filter(Boolean).join('. ')}</p>
)}
</div>
</div>
@@ -254,9 +254,9 @@ export function ScopeDecisionTab({
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</svg>
<span className="font-medium text-gray-900">{trigger.description}</span>
<span className="font-medium text-gray-900">{trigger.rule.description}</span>
<span className="text-xs px-2 py-0.5 rounded-full bg-red-200 text-red-800 font-medium">
Min. {trigger.minimumLevel}
Min. {trigger.rule.minimumLevel}
</span>
</div>
<svg
@@ -272,18 +272,18 @@ export function ScopeDecisionTab({
</button>
{expandedTrigger === idx && (
<div className="px-4 pb-4 pt-2 border-t border-gray-200">
<p className="text-sm text-gray-700 mb-2">{trigger.description}</p>
{trigger.legalReference && (
<p className="text-sm text-gray-700 mb-2">{trigger.explanation}</p>
{trigger.rule.legalReference && (
<p className="text-xs text-gray-600 mb-2">
<span className="font-medium">Rechtsgrundlage:</span> {trigger.legalReference}
<span className="font-medium">Rechtsgrundlage:</span> {trigger.rule.legalReference}
</p>
)}
{trigger.category && (
{trigger.rule.mandatoryDocuments && trigger.rule.mandatoryDocuments.length > 0 && (
<p className="text-xs text-gray-700">
<span className="font-medium">Kategorie:</span> {trigger.category}
<span className="font-medium">Pflichtdokumente:</span> {trigger.rule.mandatoryDocuments.join(', ')}
</p>
)}
{trigger.requiresDSFA && (
{trigger.rule.dsfaRequired && (
<p className="text-xs text-orange-700 font-medium mt-1">DSFA erforderlich</p>
)}
</div>
@@ -317,21 +317,21 @@ export function ScopeDecisionTab({
<span className="font-medium text-gray-900">
{DOCUMENT_TYPE_LABELS[doc.documentType] || doc.documentType}
</span>
{doc.isMandatory && (
{doc.required && (
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800">
Pflicht
</span>
)}
</div>
</td>
<td className="py-3 px-4 text-sm text-gray-700">{doc.depthDescription}</td>
<td className="py-3 px-4 text-sm text-gray-700">{doc.depth}</td>
<td className="py-3 px-4 text-sm text-gray-700">
{doc.effortEstimate ? `${doc.effortEstimate.days} Tage` : '-'}
{doc.estimatedEffort || '-'}
</td>
<td className="py-3 px-4">
{doc.triggeredByHardTrigger && (
{doc.triggeredBy && doc.triggeredBy.length > 0 && (
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800">
Hard-Trigger
{doc.triggeredBy.join(', ')}
</span>
)}
</td>
@@ -375,11 +375,11 @@ export function ScopeDecisionTab({
)}
{/* Gap Analysis */}
{decision.gapAnalysis && decision.gapAnalysis.length > 0 && (
{decision.gaps && decision.gaps.length > 0 && (
<div className="bg-white rounded-xl border border-gray-200 p-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Gap-Analyse</h3>
<div className="space-y-4">
{decision.gapAnalysis.map((gap, idx) => (
{decision.gaps.map((gap, idx) => (
<div key={idx} className="border border-gray-200 rounded-lg p-4">
<div className="flex items-start justify-between mb-2">
<h4 className="font-semibold text-gray-900">{gap.title}</h4>

View File

@@ -388,11 +388,11 @@ export const DEPTH_LEVEL_DESCRIPTIONS: Record<ComplianceDepthLevel, string> = {
/**
* Farben für Compliance-Levels (Tailwind-kompatibel)
*/
export const DEPTH_LEVEL_COLORS: Record<ComplianceDepthLevel, string> = {
L1: 'green',
L2: 'blue',
L3: 'amber',
L4: 'red',
export const DEPTH_LEVEL_COLORS: Record<ComplianceDepthLevel, { bg: string; border: string; badge: string; text: string }> = {
L1: { bg: 'bg-green-50', border: 'border-green-300', badge: 'bg-green-100', text: 'text-green-800' },
L2: { bg: 'bg-blue-50', border: 'border-blue-300', badge: 'bg-blue-100', text: 'text-blue-800' },
L3: { bg: 'bg-amber-50', border: 'border-amber-300', badge: 'bg-amber-100', text: 'text-amber-800' },
L4: { bg: 'bg-red-50', border: 'border-red-300', badge: 'bg-red-100', text: 'text-red-800' },
};
/**

View File

@@ -30,14 +30,19 @@
### Build & Run
```bash
# Build
# Build (lokal)
cd ai-compliance-sdk
go build -o server ./cmd/server
# Run
# Run (lokal)
./server --config config.yaml
# Alternativ: mit Docker
# Production: CI/CD (automatisch bei Push auf main)
git push origin main && git push gitea main
# → Gitea Actions: Tests → Build → Deploy auf Hetzner
# → Status: https://gitea.meghsakha.com/Benjamin_Boenisch/breakpilot-compliance/actions
# Alternativ: mit Docker (lokal)
docker compose up -d
```
@@ -445,8 +450,24 @@ metadata:
```bash
cd ai-compliance-sdk
go test -v ./...
# So wie die CI es ausfuehrt (CGO_ENABLED=0):
CGO_ENABLED=0 go test -v -coverprofile=coverage.out ./...
```
### CI/CD Pipeline
Tests laufen automatisch bei jedem Push via Gitea Actions (`.gitea/workflows/ci.yaml`):
| Job | Container | Was wird getestet |
|-----|-----------|-------------------|
| `test-go-ai-compliance` | `golang:1.24-alpine` | `go test -v ./...` |
| `test-python-backend-compliance` | `python:3.12-slim` | `pytest compliance/tests/` |
| `test-python-document-crawler` | `python:3.12-slim` | `pytest tests/` |
| `test-python-dsms-gateway` | `python:3.12-slim` | `pytest test_main.py` |
Nach erfolgreichen Tests: automatisches Deploy auf Hetzner (`deploy-hetzner` Job).
### Spezifische Tests
```bash
@@ -1008,4 +1029,4 @@ cd admin-v2 && npm test -- --testPathPattern=dsfa
---
*Dokumentationsstand: 2026-02-09*
*Dokumentationsstand: 2026-03-11*