Richtlinien-Update: 316 Anforderungen/45 Controls + Schutzbedarf-/TISAX-Schalter
Delta-Update des VDA-ISA-2027-Vorlagenpakets eingepflegt: - Aktualisiertes Seed-Paket (ersetzt bisherigen Stand): 316 Anforderungen (122 MUSS · 132 SOLL · 43 HOCH · 19 SEHR HOCH) über 45 Controls; VA-01/VA-05 jetzt enthalten (13 Verfahren vollständig). Beschädigte RACI-Tokens (VA-05/08/09/ 10/12/13) repariert. Importer: Umsetzungstext aus den .md-IMPL-Ankern extrahiert (mapping.json führt ihn nicht mehr), neue Obligation-Typen HOCH/SEHR HOCH. - Neue Schutzbedarf-Flags (variables.schema): FLAG_HIGH_PROTECTION, FLAG_VERY_HIGH_PROTECTION, FLAG_ELEVATED_PROTECTION (abgeleitet). Render-Helper applyProtection: HIGH stets an, VERY_HIGH aus Global/Override, ELEVATED = HIGH||VH (nie manuell) — angewandt in Lese-, Bearbeiten-, Handbuch- und Coverage-Rendering. - TISAX-Level-Schalter (AL2/AL3) zentral auf der Bibliothek (setGlobalTisaxLevel); AL2 = MUSS/SOLL/HOCH, AL3 = zusätzlich SEHR HOCH. Override je Richtlinie im Bearbeitungsmodus (setProtectionOverride, Feld protection_override); effektiver Wert = Dokument-Override sonst global. - KPIs zeigen 316 Anforderungen mit Aufschlüsselung; Coverage/Badges für HOCH/SEHR HOCH; Control-Titel-Fallback. Verifiziert: Import 316/45; Rendering rückstandsfrei über AL2/AL3 × Flag-Kombis; Override R04→AL3 zeigt SEHR-HOCH-Inhalt, R02 (global AL2) nicht; global bleibt AL2. Architektur-Hinweis: applyProtection kapselt das Level→Flags-Mapping, sodass die globale Ebene später ohne Umbau zur TISAX-AL2/AL3-Auswahl wird (bereits so gebaut). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,23 @@ function titleOf(md: string): string {
|
||||
const m = md.match(/^#\s+(.+?)\s*$/m);
|
||||
return m ? m[1].trim() : "(ohne Titel)";
|
||||
}
|
||||
/** Umsetzungstext je Anforderung aus den `<!-- IMPL id -->`-Ankern extrahieren. */
|
||||
function extractImpls(raw: string, into: Map<string, string>) {
|
||||
const lines = raw.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const m = lines[i].match(/^<!--\s*IMPL\s+(\S+)\s*-->/);
|
||||
if (!m) continue;
|
||||
const buf: string[] = [];
|
||||
for (let j = i + 1; j < lines.length; j++) {
|
||||
const l = lines[j];
|
||||
const tr = l.trim();
|
||||
if (tr === "" || tr.startsWith("<!--") || tr.startsWith("{{#") || tr.startsWith("{{/") || /^#{1,6}\s/.test(tr) || tr.startsWith("**") || tr.startsWith("- ") || tr.startsWith("|")) break;
|
||||
buf.push(l);
|
||||
}
|
||||
if (buf.length) into.set(m[1], buf.join(" ").trim());
|
||||
}
|
||||
}
|
||||
|
||||
function varGroup(key: string): string {
|
||||
if (key.startsWith("FLAG_")) return "Feature-Flags";
|
||||
if (key.startsWith("ORG_") || key.startsWith("ISMS_")) return "Organisation";
|
||||
@@ -49,12 +66,13 @@ export async function importPolicies(prisma: PrismaClient, tenantId: string, see
|
||||
const mapping = JSON.parse(readFileSync(join(seedDir, "mapping.json"), "utf-8")) as {
|
||||
anforderungen: Array<{
|
||||
id: string; policy: string; control: string; type: string;
|
||||
condition: string | null; requirement: string; implementation: string; nachweis_link?: string;
|
||||
condition: string | null; requirement: string; implementation?: string; nachweis_link?: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
// ── 2. Dokumente einlesen (Richtlinien + Verfahren) ──────────────────────
|
||||
const reqToVas = new Map<string, Set<string>>();
|
||||
const implMap = new Map<string, string>(); // Umsetzungstext je Anforderung aus den IMPL-Ankern
|
||||
const docs: Array<{ code: string; type: DocType; title: string; policyCode: string | null; fulfills: string[]; raw: string; orderIdx: number }> = [];
|
||||
|
||||
const richtDir = join(seedDir, "richtlinien");
|
||||
@@ -63,6 +81,7 @@ export async function importPolicies(prisma: PrismaClient, tenantId: string, see
|
||||
const code = docCodeFromFile(file);
|
||||
const type: DocType = code === "L00" ? "LEITLINIE" : "RICHTLINIE";
|
||||
const orderIdx = code === "L00" ? 0 : parseInt(code.replace(/\D/g, ""), 10);
|
||||
extractImpls(raw, implMap);
|
||||
docs.push({ code, type, title: titleOf(raw), policyCode: null, fulfills: [], raw, orderIdx });
|
||||
}
|
||||
|
||||
@@ -101,7 +120,7 @@ export async function importPolicies(prisma: PrismaClient, tenantId: string, see
|
||||
await prisma.policyRequirement.create({
|
||||
data: {
|
||||
tenantId, reqId: a.id, policyCode: a.policy, control: a.control, obligation: a.type,
|
||||
condition: a.condition, requirement: a.requirement, implementation: a.implementation,
|
||||
condition: a.condition, requirement: a.requirement, implementation: implMap.get(a.id) ?? a.implementation ?? "",
|
||||
vaCodes: [...(reqToVas.get(a.id) ?? [])].sort(), nachweisLink: a.nachweis_link ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user