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
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:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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' },
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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*
|
||||
|
||||
Reference in New Issue
Block a user