Files
breakpilot-compliance/docs-src/services/sdk-modules/multi-project.md
Benjamin Admin 0affa4eb66
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 33s
CI / test-python-backend-compliance (push) Successful in 34s
CI / test-python-document-crawler (push) Successful in 23s
CI / test-python-dsms-gateway (push) Successful in 19s
feat(sdk): Multi-Projekt-Architektur — mehrere Projekte pro Tenant
Jeder Tenant kann jetzt mehrere Compliance-Projekte anlegen (z.B. verschiedene
Produkte, Tochterunternehmen). CompanyProfile ist pro Projekt kopierbar und
danach unabhaengig editierbar. Multi-Tab-Support via separater BroadcastChannel
und localStorage Keys pro Projekt.

- Migration 039: compliance_projects Tabelle, sdk_states.project_id
- Backend: FastAPI CRUD-Routes fuer Projekte mit Tenant-Isolation
- Frontend: ProjectSelector UI, SDKProvider mit projectId, URL ?project=
- State API: UPSERT auf (tenant_id, project_id) mit Abwaertskompatibilitaet
- Tests: pytest fuer Model-Validierung, Row-Konvertierung, Tenant-Isolation
- Docs: MKDocs Seite, CLAUDE.md, Backend README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 14:53:50 +01:00

5.7 KiB

Multi-Projekt-Architektur

Jeder Tenant kann mehrere Compliance-Projekte anlegen (z.B. verschiedene Produkte, Tochterunternehmen). CompanyProfile ist pro Projekt — nicht tenant-weit.

Uebersicht

graph TD
    T[Tenant] --> P1[Projekt A: KI-Produkt X]
    T --> P2[Projekt B: SaaS API]
    T --> P3[Projekt C: Tochter GmbH]
    P1 --> S1[SDK State A]
    P2 --> S2[SDK State B]
    P3 --> S3[SDK State C]
    S1 --> CP1[CompanyProfile A]
    S2 --> CP2[CompanyProfile B]
    S3 --> CP3[CompanyProfile C]

Datenmodell

compliance_projects

Spalte Typ Beschreibung
id UUID Primaerschluessel
tenant_id VARCHAR(255) Tenant-Zuordnung
name VARCHAR(500) Projektname
description TEXT Beschreibung
customer_type VARCHAR(20) 'new' oder 'existing'
status VARCHAR(20) 'active', 'archived', 'deleted'
project_version INTEGER Versionszaehler
completion_percentage INTEGER Fortschritt (0-100)
created_at TIMESTAMPTZ Erstellungszeitpunkt
updated_at TIMESTAMPTZ Letzte Aenderung
archived_at TIMESTAMPTZ Archivierungszeitpunkt

sdk_states (erweitert)

  • UNIQUE-Constraint auf (tenant_id, project_id) statt nur tenant_id
  • project_id UUID NOT NULL — FK auf compliance_projects(id) ON DELETE CASCADE

Daten-Ownership

Daten Scope Speicherort
Firmenname, Rechtsform, DSB, Standorte Pro Projekt sdk_states.state.companyProfile
Projektname, Typ, Status Projekt compliance_projects
SDK State (VVT, DSFA, TOM, etc.) Projekt sdk_states (JSONB)

Backend API

Alle Endpoints sind tenant-isoliert via X-Tenant-ID Header.

Endpoints

Method Endpoint Beschreibung
GET /api/v1/projects Alle aktiven Projekte des Tenants
POST /api/v1/projects Neues Projekt erstellen
GET /api/v1/projects/{id} Einzelnes Projekt laden
PATCH /api/v1/projects/{id} Projekt aktualisieren
DELETE /api/v1/projects/{id} Projekt archivieren (Soft Delete)

Projekt erstellen

POST /api/v1/projects
{
    "name": "KI-Produkt X",
    "description": "DSGVO-Compliance fuer Produkt X",
    "customer_type": "existing",
    "copy_from_project_id": "uuid-123"
}

Response (201):

{
    "id": "uuid-new",
    "tenant_id": "uuid-tenant",
    "name": "KI-Produkt X",
    "description": "DSGVO-Compliance fuer Produkt X",
    "customer_type": "existing",
    "status": "active",
    "project_version": 1,
    "completion_percentage": 0,
    "created_at": "2026-03-09T12:00:00Z",
    "updated_at": "2026-03-09T12:00:00Z"
}

Stammdaten-Kopie

Wenn copy_from_project_id angegeben, kopiert das Backend companyProfile aus dem Quell-State in den neuen State. Die kopierten Daten sind danach unabhaengig editierbar.

Anwendungsfall: Konzern mit Tochterfirmen — gleiche Rechtsform, aber unterschiedliche Adresse/Mitarbeiterzahl.

Projekt archivieren

DELETE /api/v1/projects/{id}

Setzt status='archived' und archived_at=NOW(). Archivierte Projekte erscheinen nicht in der Standardliste (nur mit ?include_archived=true).

Frontend

URL-Schema

/sdk                      → Projektliste (ProjectSelector)
/sdk?project={uuid}       → Dashboard im Projekt-Kontext
/sdk/vvt?project={uuid}   → VVT im Projekt-Kontext
/sdk/dsfa?project={uuid}  → DSFA im Projekt-Kontext

Alle internen Links enthalten automatisch ?project=.

Komponenten

Komponente Datei Beschreibung
ProjectSelector components/sdk/ProjectSelector/ProjectSelector.tsx Projektliste + Erstellen-Dialog
ProjectCard (gleiche Datei) Einzelne Projektkarte
CreateProjectDialog (gleiche Datei) Modal fuer neues Projekt

State-Isolation (Multi-Tab)

  • BroadcastChannel: sdk-state-sync-{tenantId}-{projectId} — pro Projekt
  • localStorage: ai-compliance-sdk-state-{tenantId}-{projectId} — pro Projekt
  • Tab A (Projekt X) und Tab B (Projekt Y) interferieren nicht

SDKProvider

<SDKProvider
  enableBackendSync={true}
  projectId={searchParams.get('project')}
>
  {children}
</SDKProvider>

Context-Methoden

const {
  createProject,    // (name, customerType) => Promise<ProjectInfo>
  listProjects,     // () => Promise<ProjectInfo[]>
  switchProject,    // (projectId) => void (navigiert zu ?project=)
  archiveProject,   // (projectId) => Promise<void>
  projectId,        // aktuelles Projekt-UUID
} = useSDK()

Migration (039)

Datei: backend-compliance/migrations/039_compliance_projects.sql

  1. Erstellt compliance_projects Tabelle
  2. Entfernt UNIQUE(tenant_id) von sdk_states
  3. Fuegt project_id UUID zu sdk_states hinzu
  4. Migriert bestehende Daten (Default-Projekt pro existierendem State)
  5. Setzt project_id auf NOT NULL

Migration ausfuehren

ssh macmini "/usr/local/bin/docker exec bp-compliance-backend \
  psql \$COMPLIANCE_DATABASE_URL -f /app/migrations/039_compliance_projects.sql"

Tests

# Backend-Tests
ssh macmini "/usr/local/bin/docker exec bp-compliance-backend \
  pytest tests/test_project_routes.py -v"
Test Beschreibung
TestCreateProjectRequest Model-Validierung (Name, Defaults)
TestUpdateProjectRequest Partial Update Model
TestRowToResponse DB-Row-zu-Response Konvertierung
TestCreateProjectCopiesProfile Copy-Request Model
TestTenantIsolation SQL-Queries filtern nach tenant_id
TestStateIsolation sdk_states + companyProfile pro Projekt