Lieferantenmodul neu: Asset-basiert + Anforderungs-Engine (Phase 1)

Referenz: docs/ISMS-Lieferantenmanagement-GEFIM.html

Architektur: Lieferanten (und IT-Services) sind jetzt Assets.
- AssetType += IT_SERVICE; SupplierProfile/ITServiceProfile als 1:1-
  Erweiterung eines Asset; alle Kind-Entitäten (Contract, Nda,
  SupplierEvidence, SupplierAssessment, ManagementDecision, Subcontractor,
  ServiceControlResponsibility, MaturityAssessment) hängen am Asset
  (keine parallele Datenhaltung). Migration + RLS; Demo neu geseedet.
- Lieferanten erscheinen im Asset-Inventar (Filter „Lieferant"/„IT-Service"),
  tragen C/I/A, nutzbar in Graph/BIA/Risiko.

Anforderungs-Engine (Herzstück, src/lib/supplier.ts):
- Schutzbedarf aus max C/I/A der verknüpften Assets → Stufe normal/hoch/
  sehr hoch; schaltet Anforderungen gestuft scharf (must/should/high/veryhigh)
- Flache Anforderungsliste (nach Themen gruppiert) mit Status-Ableitung aus
  den hinterlegten Objekten, Referenz + Herkunfts-Control (6.1.1–6.1.3)
- Gate-Logik: sehr hoch ohne Audit/Label → Kompensation (Management-
  entscheidung UND verknüpftes Risiko); „Risiko anlegen" erzeugt echten Risk
- Konformität (Konform/Teilweise/Lücken/Handlung nötig) + berechneter
  Reifegrad; ISB-Freigabe (Abweichung nur mit Begründung → Audit-Log)
- Cockpit-Detail mit Schutzbedarf-Banner + Live-Simulation der Stufe

Verifiziert: Register mit abgeleiteter Stufe/Reifegrad/Konformität,
Cockpit-Simulation (Tiers werden inaktiv), Gate bei sehr hoch ohne Audit,
„Risiko anlegen" erzeugt R-005 im Risikomodul.

Offen (Phase 2): Fragebogen-Builder, Self-Service-Portal, IT-Service-
Detail mit RACI-Matrix, Klick im Asset-Inventar öffnet Cockpit,
Scheduler-Automatisierung.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Martin
2026-07-03 11:57:17 +02:00
co-authored by Claude Opus 4.8
parent 32ab91efbf
commit dc884062b2
17 changed files with 1605 additions and 972 deletions
+20 -157
View File
@@ -453,168 +453,31 @@ async function main() {
console.log(`${measures.length} Beispiel-Maßnahmen angelegt, Rest-Risiken berechnet`);
}
// 8. VDA-ISA 2027 Kapitel 6 — Supplier Relationships (globaler Katalog)
const controls = [
{
ref: "6.1.1",
title:
"To what extent is information security ensured among contractors and cooperation partners?",
objective:
"Ein angemessenes Informationssicherheitsniveau wird auch bei der Zusammenarbeit mit Partnern und Auftragnehmern aufrechterhalten.",
mustReq:
"Auftragnehmer/Partner werden einer Sicherheits­risikobewertung unterzogen; angemessenes Niveau vertraglich sichergestellt; Kundenanforderungen ggf. weitergegeben.",
shouldReq:
"Vertragliche Verpflichtung zur Weitergabe an Subunternehmer; Prüfung von Service-Reports/Dokumenten.",
highReq:
"Nachweis eines angemessenen Sicherheitsniveaus (geprüfter Fragebogen/Self-Assessment, Attest, Zertifikat, Lieferantenaudit) (C,I,A); Compliance dokumentiert, regelmäßig & anlassbezogen überwacht.",
veryHighReq:
"Nachweis durch Third-Party-Audit (adäquates TISAX-Label o. Ä.) oder Lieferantenaudit; ohne Audit: risikobasierte Management­entscheidung mit Protokoll (C,I,A); Transparenzpflichten gegenüber Kunden erfüllt.",
targetMaturity: 3,
simplifiedGroupAssessment: true,
references:
"ISO 27001:2022 A.5.19A.5.22 · NIST CSF 2.0 GV.SC-02..06 · BSI OPS.2.1/OPS.2.2/OPS.3.1/ORP.2 · NIST SP800-53r5 MA-4, CA-3, CA-6, PM-16, PM-30, SR-2, SR-3, SR-6, SR-7, SR-8",
},
{
ref: "6.1.2",
title:
"To what extent is non-disclosure regarding the exchange of information contractually agreed?",
objective:
"Geheimhaltungsvereinbarungen schützen den Informationsaustausch über Organisationsgrenzen hinweg rechtlich.",
mustReq:
"Geheimhaltungs­anforderungen bestimmt und erfüllt; allen Beteiligten bekannt; gültige NDAs vor Weitergabe sensibler Infos; regelmäßige Überprüfung.",
shouldReq:
"Geprüfte NDA-Vorlagen; NDAs mit Parteien, Informationsart, Gegenstand, Gültigkeit, Pflichten; Nachweis-/Auditrechte; Prozess zur Fristenüberwachung und rechtzeitigen Verlängerung.",
highReq: null,
veryHighReq: null,
targetMaturity: 3,
simplifiedGroupAssessment: true,
references: "ISO 27001:2022 A.5.14, A.6.6 · BSI OPS.2.1/OPS.2.2/OPS.3.1/ORP.5/CON.2",
},
{
ref: "6.1.3",
title:
"To what extent are the responsibilities between external IT service providers and the own organization defined?",
objective:
"Gemeinsames Verständnis der Verantwortungsteilung; alle Sicherheitsanforderungen umgesetzt und nachweislich dokumentiert.",
mustReq:
"Betroffene IT-Services identifiziert; Anforderungen bestimmt; verantwortliche Organisation je Anforderung definiert; Mechanismen für geteilte Verantwortung umgesetzt.",
shouldReq:
"Konfiguration konzeptioniert/umgesetzt/dokumentiert; zuständiges Personal geschult.",
highReq:
"Liste der IT-Services und Provider (C,I,A); ISA-Control-Anwendbarkeit bewertet; regelmäßige Security-Assessments; Nachweis der Pflichterfüllung; Integration in lokale Schutzmaßnahmen dokumentiert.",
veryHighReq: null,
targetMaturity: 3,
simplifiedGroupAssessment: false,
references:
"ISO 27001:2022 A.5.23, A.8.9 · ISO 27017 CLD.6.3.1 · IEC 62443-2-1 6.2.3 · NIST CSF 2.0 GV.OC-05, GV.SC-01/02 · BSI 200-2, OPS.2.1/OPS.2.2/OPS.3.1/ORP.2 · NIST SP800-53r5 MA-4, PT-1, PL-2",
},
];
for (const c of controls) {
await prisma.supplierControl.upsert({ where: { ref: c.ref }, update: c, create: c });
}
console.log(`✔ VDA-ISA 2027 Kap. 6: ${controls.length} Supplier-Controls`);
// 8. Demo-Lieferanten als Assets (type SUPPLIER) mit Profil, Nachweisen, Verträgen
const supCount = await prisma.supplierProfile.count({ where: { tenantId: tenant.id } });
if (supCount === 0) {
const hoster = await prisma.asset.findFirst({ where: { tenantId: tenant.id, name: "Cloud-Hoster (IaaS)" } });
// 9. Demo-Lieferant mit Nachweisen/Verträgen (nur wenn noch keiner existiert)
const supplierCount = await prisma.supplier.count({ where: { tenantId: tenant.id } });
if (supplierCount === 0) {
const hoster = await prisma.asset.findFirst({
where: { tenantId: tenant.id, name: "Cloud-Hoster (IaaS)" },
const a1 = await prisma.asset.create({
data: { tenantId: tenant.id, name: "Cloud-Hoster GmbH", type: "SUPPLIER", confidentiality: 3, integrity: 3, availability: 4 },
});
const sup = await prisma.supplier.create({
data: {
tenantId: tenant.id,
refNo: 1,
name: "Cloud-Hoster GmbH",
sector: "IT-Dienstleistung / IaaS",
services: "Rechenzentrum, Virtualisierung, Backup für ERP & CRM",
criticality: 4,
dataCategories: ["Kundendaten", "Auftragsdaten"],
confidentiality: 3,
integrity: 3,
availability: 4,
nis2Relevant: true,
status: "ACTIVE",
contact: "security@cloud-hoster.example",
nextReview: new Date(Date.now() + 90 * 24 * 3600 * 1000),
},
await prisma.supplierProfile.create({
data: { tenantId: tenant.id, assetId: a1.id, refNo: 1, sector: "IT-Dienstleistung / IaaS", serviceDesc: "Rechenzentrum, Virtualisierung, Backup", criticality: 4, dataCategories: ["Kundendaten", "Auftragsdaten"], nis2Relevant: true, lifecycle: "ACTIVE", contact: "security@cloud-hoster.example", nextReview: new Date(Date.now() + 90 * 24 * 3600 * 1000) },
});
if (hoster) {
await prisma.supplierAsset.create({
data: { tenantId: tenant.id, supplierId: sup.id, assetId: hoster.id },
});
}
await prisma.supplierEvidence.create({
data: {
tenantId: tenant.id,
supplierId: sup.id,
kind: "TISAX_LABEL",
name: "TISAX AL3 (info high)",
protectsCia: "C,I,A",
validTo: new Date(Date.now() + 200 * 24 * 3600 * 1000),
adequacyChecked: true,
},
if (hoster) await prisma.assetRelation.create({ data: { tenantId: tenant.id, assetId: a1.id, relatedAssetId: hoster.id, type: "provides" } }).catch(() => {});
await prisma.supplierEvidence.create({ data: { tenantId: tenant.id, assetId: a1.id, kind: "TISAX_LABEL", name: "TISAX AL3 (info high)", protectsCia: "C,I,A", validTo: new Date(Date.now() + 200 * 24 * 3600 * 1000), adequacyChecked: true } });
await prisma.contract.create({ data: { tenantId: tenant.id, assetId: a1.id, type: "av_dpa", avDpa: true, securityClauses: true, flowdown: true, customerRequirementsPassed: true, validTo: new Date(Date.now() + 400 * 24 * 3600 * 1000), reference: "AV-2025-014" } });
await prisma.nda.create({ data: { tenantId: tenant.id, assetId: a1.id, subject: "Betrieb der ERP-/CRM-Infrastruktur", parties: "Demo GmbH / Cloud-Hoster GmbH", validTo: new Date(Date.now() + 60 * 24 * 3600 * 1000), extensionStatus: "offen" } });
await prisma.supplierAssessment.create({ data: { tenantId: tenant.id, assetId: a1.id, type: "SELF_ASSESSMENT", score: 82, date: new Date(Date.now() - 120 * 24 * 3600 * 1000), nextReview: new Date(Date.now() + 245 * 24 * 3600 * 1000), result: "angemessen" } });
const a2 = await prisma.asset.create({
data: { tenantId: tenant.id, name: "WebAgentur X", type: "SUPPLIER", confidentiality: 2, integrity: 2, availability: 2 },
});
await prisma.contract.create({
data: {
tenantId: tenant.id,
supplierId: sup.id,
type: "av_dpa",
avDpa: true,
securityClauses: true,
flowdown: true,
customerTransparency: false,
validFrom: new Date(Date.now() - 300 * 24 * 3600 * 1000),
validTo: new Date(Date.now() + 400 * 24 * 3600 * 1000),
reference: "AV-2025-014",
},
await prisma.supplierProfile.create({
data: { tenantId: tenant.id, assetId: a2.id, refNo: 2, sector: "Webentwicklung", serviceDesc: "Website-Betrieb", criticality: 2, dataCategories: ["Marketingdaten"], nis2Relevant: false, lifecycle: "UNDER_REVIEW" },
});
await prisma.nda.create({
data: {
tenantId: tenant.id,
supplierId: sup.id,
parties: "Demo GmbH ↔ Cloud-Hoster GmbH",
infoScope: "Betriebs- und Kundendaten",
subject: "Betrieb der ERP-/CRM-Infrastruktur",
validFrom: new Date(Date.now() - 300 * 24 * 3600 * 1000),
validTo: new Date(Date.now() + 60 * 24 * 3600 * 1000),
extensionStatus: "offen",
},
});
await prisma.supplierAssessment.create({
data: {
tenantId: tenant.id,
supplierId: sup.id,
type: "SELF_ASSESSMENT",
status: "EVALUATED",
score: 82,
date: new Date(Date.now() - 120 * 24 * 3600 * 1000),
nextReview: new Date(Date.now() + 245 * 24 * 3600 * 1000),
result: "angemessen",
},
});
await prisma.serviceResponsibility.create({
data: {
tenantId: tenant.id,
supplierId: sup.id,
itService: "IaaS-Plattform",
requirement: "Patch-Management der Hypervisor-Ebene",
responsibleParty: "SUPPLIER",
isaApplicability: "5.x IT/Cyber Security",
integratedLocalControls: "Sichere Authentisierung, Monitoring beim Kunden",
},
});
const dbControls = await prisma.supplierControl.findMany();
for (const c of dbControls) {
await prisma.supplierControlMaturity.create({
data: {
tenantId: tenant.id,
supplierId: sup.id,
controlId: c.id,
maturity: c.ref === "6.1.2" ? 2 : 3,
},
});
}
console.log("✔ Demo-Lieferant mit Nachweisen/Vertrag/NDA/Assessment angelegt");
console.log("✔ 2 Demo-Lieferanten als Assets angelegt");
}
}