Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
// 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<string, string> = {
|
||||
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<Record<string, number>>((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)")));
|
||||
Reference in New Issue
Block a user