// Generator (Story A2-2): parst die C1-Scoping-Tabelle (Fachcontent) in die // maschinenlesbare Scope-Datengrundlage `seed/scoping/c1-scope.json`. // Lauf: npx tsx scripts/build-c1-scope.ts // // Spalten der C1-Tabelle: Control | Anforderungs-ID | Typ | AL2 | AL3 | Prüfziel | Scope-Bedingung(Flag) // `condition` wird normalisiert: exaktes Feature-Flag (FLAG_*) → Flag-Name, sonst null // ("immer im Scope" bzw. "Prüfziel … aktiv" werden allein über das Prüfziel gegatet). import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; import { dirname, resolve } from "node:path"; const SRC = resolve("docs/wizard-uebergabe/02_Fachcontent_C1-C9/C1_Scoping-AL-Pruefziel.md"); const OUT = resolve("seed/scoping/c1-scope.json"); const PRUEFZIEL: Record = { Informationssicherheit: "informationssicherheit", Prototypenschutz: "prototypenschutz", Datenschutz: "datenschutz", }; const FLAG_RE = /^FLAG_[A-Z_]+$/; interface C1Row { id: string; control: string; type: "MUSS" | "SOLL" | "HOCH" | "SEHR HOCH"; al2: boolean; al3: boolean; pruefziel: string; condition: string | null; } const rows: C1Row[] = []; for (const line of readFileSync(SRC, "utf8").split("\n")) { if (!line.startsWith("| ")) continue; const cells = line.split("|").map((c) => c.trim()); // cells[0] = "" (vor dem ersten |); Nutzdaten ab cells[1] const [, control, id, type, al2, al3, pruefzielText, condRaw] = cells; if (!id || id === "Anforderungs-ID" || control.startsWith("---")) continue; // Header/Separator const pruefziel = PRUEFZIEL[pruefzielText]; if (!pruefziel) continue; // keine gültige Datenzeile const condClean = (condRaw ?? "").replace(/`/g, "").trim(); const condition = FLAG_RE.test(condClean) ? condClean : null; rows.push({ id, control, type: type as C1Row["type"], al2: al2 === "Ja", al3: al3 === "Ja", pruefziel, condition, }); } mkdirSync(dirname(OUT), { recursive: true }); writeFileSync(OUT, JSON.stringify(rows, null, 2) + "\n"); // Kurzstatistik zur Kontrolle const by = (f: (r: C1Row) => string) => rows.reduce>((a, r) => ((a[f(r)] = (a[f(r)] ?? 0) + 1), a), {}); console.log(`✓ ${rows.length} Anforderungen → seed/scoping/c1-scope.json`); console.log(" Prüfziele:", JSON.stringify(by((r) => r.pruefziel))); console.log(" Typen:", JSON.stringify(by((r) => r.type))); console.log(" Bedingungen:", JSON.stringify(by((r) => r.condition ?? "(immer/Prüfziel)")));