// Import des Standard-Risikokatalogs (Story A6-1) aus dem Fachcontent C4 in das // globale Modell RiskCatalogEntry. Tabellenzeile: // // | R-ORG-01 | Titel | Beschreibung | 1.1.1, 1.2.1 | Richtlinien, Organisation | Standardmaßnahme | E3/S4 — Begründung | // // Idempotent (Upsert über code). Kein tenantId (globaler Katalog). import { readFileSync } from "node:fs"; import { join } from "node:path"; import type { PrismaClient } from "@prisma/client"; const C4_PATH = join(__dirname, "..", "docs", "wizard-uebergabe", "02_Fachcontent_C1-C9", "C4_Risikokatalog.md"); export interface ParsedRisk { code: string; category: string; title: string; description: string; controls: string[]; assetTypes: string[]; standardMeasure: string; defaultLikelihood: number; defaultImpact: number; rationale: string; orderIdx: number; } const splitList = (s: string): string[] => s.split(",").map((x) => x.trim()).filter(Boolean); /** Parst die C4-Tabellen zu Katalog-Objekten (ohne DB-Zugriff — testbar). */ export function parseRiskCatalog(text: string): ParsedRisk[] { const out: ParsedRisk[] = []; let i = 0; for (const line of text.split("\n")) { const m = line.match(/^\|\s*(R-[A-Z]+-\d+)\s*\|(.*)\|\s*$/); if (!m) continue; const cols = m[2].split("|").map((c) => c.trim()); if (cols.length < 6) continue; // title|desc|controls|assetTypes|measure|ES-rationale const code = m[1]; const es = cols[5].match(/E\s*(\d)\s*\/\s*S\s*(\d)/i); const [, esL, esI] = es ?? []; out.push({ code, category: code.split("-")[1], title: cols[0], description: cols[1], controls: splitList(cols[2]), assetTypes: splitList(cols[3]), standardMeasure: cols[4], defaultLikelihood: esL ? Number(esL) : 3, defaultImpact: esI ? Number(esI) : 3, rationale: cols[5].replace(/^E\s*\d\s*\/\s*S\s*\d\s*[—-]\s*/i, "").trim(), orderIdx: i++, }); } return out; } /** Liest C4 und schreibt den Katalog (Upsert je code). Liefert die Anzahl. */ export async function importRiskCatalog(prisma: PrismaClient): Promise { const text = readFileSync(C4_PATH, "utf-8"); const risks = parseRiskCatalog(text); for (const r of risks) { await prisma.riskCatalogEntry.upsert({ where: { code: r.code }, update: { category: r.category, title: r.title, description: r.description, controls: r.controls, assetTypes: r.assetTypes, standardMeasure: r.standardMeasure, defaultLikelihood: r.defaultLikelihood, defaultImpact: r.defaultImpact, rationale: r.rationale, orderIdx: r.orderIdx }, create: r, }); } return risks.length; }