Iteration Teil D: Lieferantenmanagement (VDA-ISA 2027 Kap. 6 + NIS2)
Datenmodell (Prisma, RLS): Supplier + SupplierAsset, SupplierAssessment, Contract, Nda, SupplierEvidence, ServiceResponsibility, Subcontractor, ManagementDecision, SupplierControl (globaler Katalog) + SupplierControlMaturity. - VDA-ISA-2027-Kap.-6-Mini-Katalog (Controls 6.1.1–6.1.3) mit Zielbild, Muss/Soll, Anforderungen für hoch/sehr hoch, Simplified Group Assessment, Ziel-Reifegrad 3 und Cross-Referenzen (ISO/NIST/BSI); im Seed befüllt - Lieferantenverzeichnis mit KPIs (gesamt, NIS2-relevant, ablaufend, Reviews fällig), Kritikalität, NIS2-Flag, Review-Fristen - Detail-Popup: Stammdaten (Sektor/Leistung/Datenkategorien/CIA), betroffene Assets, VDA-ISA-Reifegrade je Control (Ziel 3, farbige Balken), Nachweise (Angemessenheit + Ablauf), Assessments, Verträge (AV/DPA, Flow-down, Fristen), NDAs (Fristen), Shared-Responsibility- Matrix, Subunternehmer, Managemententscheidungen - Bearbeiten-Popup: Stammdaten (ein Speichern), Reifegrad je Control, Add/Delete für alle Kind-Entitäten, Löschen im ⋯-Menü - Regel 6.1.1: fehlt geprüfter Audit-/TISAX-Nachweis → Warnung, dass eine dokumentierte risikobasierte Managemententscheidung nötig ist - Server-Actions mit Zod/RBAC/Audit-Log; Seed mit Demo-Lieferant (TISAX-Label, AV/DPA, NDA, Assessment, RACI, Reifegrade) - Menüpunkt „Lieferanten" aktiv; Lieferant ↔ Asset verknüpft (Graph) Verifiziert: Register/Detail/Bearbeiten dunkel & vollständig, Reifegrad- Save (6.1.2→4 mit Audit), Managemententscheidungs-Logik. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
18bd82e54a
commit
32ab91efbf
@@ -166,6 +166,7 @@ model Asset {
|
||||
relationsTo AssetRelation[] @relation("relationTo")
|
||||
processAssets ProcessAsset[]
|
||||
riskAssets RiskAsset[]
|
||||
supplierLinks SupplierAsset[]
|
||||
|
||||
@@index([tenantId])
|
||||
@@index([tenantId, type])
|
||||
@@ -396,6 +397,253 @@ model Vulnerability {
|
||||
@@map("vulnerabilities")
|
||||
}
|
||||
|
||||
// ── Lieferantenmanagement (SPEC §4.14, VDA-ISA 2027 Kap. 6, NIS2 Art. 21(2)(d)) ──
|
||||
|
||||
enum SupplierStatus {
|
||||
ACTIVE
|
||||
ONBOARDING
|
||||
UNDER_REVIEW
|
||||
OFFBOARDED
|
||||
}
|
||||
|
||||
enum AssessmentType {
|
||||
QUESTIONNAIRE
|
||||
SELF_ASSESSMENT
|
||||
AUDIT
|
||||
}
|
||||
|
||||
enum AssessmentStatus {
|
||||
SENT
|
||||
RECEIVED
|
||||
EVALUATED
|
||||
OVERDUE
|
||||
}
|
||||
|
||||
enum EvidenceKind {
|
||||
CERTIFICATE
|
||||
TISAX_LABEL
|
||||
ATTESTATION
|
||||
AUDIT_REPORT
|
||||
SELF_ASSESSMENT
|
||||
}
|
||||
|
||||
enum ResponsibleParty {
|
||||
CLIENT
|
||||
SUPPLIER
|
||||
SHARED
|
||||
}
|
||||
|
||||
model Supplier {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
refNo Int @map("ref_no") // Anzeige "L-001"
|
||||
|
||||
name String
|
||||
sector String?
|
||||
services String? // erbrachte Leistung / IT-Services
|
||||
criticality Int @default(1) // 1–4
|
||||
dataCategories String[] @default([]) @map("data_categories")
|
||||
// Schutzbedarf der verarbeiteten Informationen (C/I/A 1–4)
|
||||
confidentiality Int @default(1)
|
||||
integrity Int @default(1)
|
||||
availability Int @default(1)
|
||||
nis2Relevant Boolean @default(false) @map("nis2_relevant") // Teil der Lieferkette
|
||||
status SupplierStatus @default(ACTIVE)
|
||||
contact String?
|
||||
nextReview DateTime? @map("next_review")
|
||||
notes String?
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
createdBy String? @map("created_by")
|
||||
|
||||
assessments SupplierAssessment[]
|
||||
contracts Contract[]
|
||||
ndas Nda[]
|
||||
evidence SupplierEvidence[]
|
||||
responsibilities ServiceResponsibility[]
|
||||
subcontractors Subcontractor[]
|
||||
decisions ManagementDecision[]
|
||||
controlMaturity SupplierControlMaturity[]
|
||||
assetLinks SupplierAsset[]
|
||||
|
||||
@@unique([tenantId, refNo])
|
||||
@@index([tenantId])
|
||||
@@map("suppliers")
|
||||
}
|
||||
|
||||
// Lieferant ↔ Asset (welcher Dienstleister betrifft welche Assets) — speist den Graph
|
||||
model SupplierAsset {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
assetId String @map("asset_id")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
asset Asset @relation(fields: [assetId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([supplierId, assetId])
|
||||
@@index([tenantId])
|
||||
@@map("supplier_assets")
|
||||
}
|
||||
|
||||
model SupplierAssessment {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
type AssessmentType
|
||||
status AssessmentStatus @default(SENT)
|
||||
score Int? // 0–100 Scoring
|
||||
date DateTime?
|
||||
nextReview DateTime? @map("next_review")
|
||||
result String?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("supplier_assessments")
|
||||
}
|
||||
|
||||
model Contract {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
type String @default("service") // service | av_dpa | nda | sla …
|
||||
avDpa Boolean @default(false) @map("av_dpa") // AV/DPA (DSGVO Art. 28)
|
||||
securityClauses Boolean @default(false) @map("security_clauses")
|
||||
flowdown Boolean @default(false) // Weitergabe an Subunternehmer
|
||||
customerTransparency Boolean @default(false) @map("customer_transparency")
|
||||
validFrom DateTime? @map("valid_from")
|
||||
validTo DateTime? @map("valid_to")
|
||||
reference String?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("contracts")
|
||||
}
|
||||
|
||||
model Nda {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
parties String?
|
||||
infoScope String? @map("info_scope")
|
||||
subject String?
|
||||
validFrom DateTime? @map("valid_from")
|
||||
validTo DateTime? @map("valid_to")
|
||||
obligations String?
|
||||
extensionStatus String? @map("extension_status") // z. B. offen | verlängert | ausgelaufen
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("ndas")
|
||||
}
|
||||
|
||||
model SupplierEvidence {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
kind EvidenceKind
|
||||
name String?
|
||||
protectsCia String? @map("protects_cia") // z. B. "C,I,A"
|
||||
validTo DateTime? @map("valid_to")
|
||||
adequacyChecked Boolean @default(false) @map("adequacy_checked")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("supplier_evidence")
|
||||
}
|
||||
|
||||
model ServiceResponsibility {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
itService String @map("it_service")
|
||||
requirement String
|
||||
responsibleParty ResponsibleParty @default(SHARED) @map("responsible_party")
|
||||
isaApplicability String? @map("isa_applicability")
|
||||
evidence String?
|
||||
integratedLocalControls String? @map("integrated_local_controls")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("service_responsibilities")
|
||||
}
|
||||
|
||||
model Subcontractor {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
name String
|
||||
flowdownObligation Boolean @default(false) @map("flowdown_obligation")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("subcontractors")
|
||||
}
|
||||
|
||||
model ManagementDecision {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
reasonNoAudit String @map("reason_no_audit")
|
||||
decision String
|
||||
decidedBy String? @map("decided_by")
|
||||
date DateTime @default(now())
|
||||
recordRef String? @map("record_ref")
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("management_decisions")
|
||||
}
|
||||
|
||||
// VDA-ISA 2027 Kapitel 6 — Supplier Relationships (globaler Katalog, per Import versioniert)
|
||||
model SupplierControl {
|
||||
id String @id @default(cuid())
|
||||
ref String @unique // 6.1.1 / 6.1.2 / 6.1.3
|
||||
title String
|
||||
objective String
|
||||
|
||||
mustReq String? @map("must_req")
|
||||
shouldReq String? @map("should_req")
|
||||
highReq String? @map("high_req") // Additional for high protection
|
||||
veryHighReq String? @map("very_high_req") // Additional for very high protection
|
||||
simplifiedGroupAssessment Boolean @default(false) @map("simplified_group_assessment")
|
||||
targetMaturity Int @default(3) @map("target_maturity")
|
||||
references String? // ISO 27001, NIST CSF, BSI …
|
||||
|
||||
maturity SupplierControlMaturity[]
|
||||
|
||||
@@map("supplier_controls")
|
||||
}
|
||||
|
||||
model SupplierControlMaturity {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
supplierId String @map("supplier_id")
|
||||
controlId String @map("control_id")
|
||||
maturity Int @default(0) // 0–5
|
||||
notes String?
|
||||
|
||||
supplier Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade)
|
||||
control SupplierControl @relation(fields: [controlId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([supplierId, controlId])
|
||||
@@index([tenantId])
|
||||
@@map("supplier_control_maturity")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
|
||||
Reference in New Issue
Block a user