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>
61 lines
2.9 KiB
TypeScript
61 lines
2.9 KiB
TypeScript
// Akzeptanztest der Funktionstrennungs-Regeln FT-01…FT-06 (Story A4-2, C7 §2).
|
|
// Reine Logik, kein DB-Zugriff. Lauf: npx tsx scripts/test-ft-rules.ts
|
|
|
|
import { evaluateFt, type FtRoleInput } from "../src/lib/ft-rules";
|
|
|
|
let failures = 0;
|
|
const ok = (cond: boolean, msg: string) => {
|
|
console.log(`${cond ? "✓" : "✗ FEHLER"} ${msg}`);
|
|
if (!cond) failures++;
|
|
};
|
|
|
|
const base: FtRoleInput = {
|
|
roles: { ISB: "Frau A", MANAGEMENT: "Herr B", IT_LEAD: "Herr C", HR_LEAD: "Frau D", DPO: "Herr E" },
|
|
isbNamed: true, isbIsIt: false, isbInternal: false, personalData: false,
|
|
};
|
|
const codes = (i: FtRoleInput) => evaluateFt(i).map((f) => f.code);
|
|
const byCode = (i: FtRoleInput, c: string) => evaluateFt(i).find((f) => f.code === c);
|
|
|
|
// — Sauberer Fall: nur FT-06 (manueller Hinweis) —
|
|
ok(JSON.stringify(codes(base)) === JSON.stringify(["FT-06"]), "sauber → nur FT-06 (manuell)");
|
|
|
|
// — FT-04: ISB nicht benannt → Lücke + Aufgabe (reuse isb_not_named) —
|
|
{
|
|
const f = byCode({ ...base, isbNamed: false }, "FT-04");
|
|
ok(!!f && f.severity === "luecke" && f.task?.origin === "isb_not_named" && f.task?.reuse === true, "FT-04 ISB nicht benannt → Lücke + Aufgabe (reuse)");
|
|
}
|
|
|
|
// — FT-01: ISB = IT → Konflikt + Aufgabe (reuse isb_equals_it) —
|
|
{
|
|
const f = byCode({ ...base, isbIsIt: true }, "FT-01");
|
|
ok(!!f && f.severity === "konflikt" && f.task?.origin === "isb_equals_it" && f.task?.reuse === true, "FT-01 ISB=IT → Konflikt + Aufgabe (reuse)");
|
|
}
|
|
|
|
// — FT-03: ISB = Leitung → Konflikt + neue Aufgabe ft-03 —
|
|
{
|
|
const f = byCode({ ...base, roles: { ...base.roles, MANAGEMENT: "Frau A" } }, "FT-03");
|
|
ok(!!f && f.severity === "konflikt" && f.task?.origin === "ft-03" && f.task?.reuse === false, "FT-03 ISB=Leitung → Konflikt + neue Aufgabe");
|
|
}
|
|
|
|
// — FT-05: DPO fehlt trotz personenbezogener Daten → Lücke + neue Aufgabe ft-05 —
|
|
{
|
|
const f = byCode({ ...base, personalData: true, roles: { ...base.roles, DPO: "" } }, "FT-05");
|
|
ok(!!f && f.severity === "luecke" && f.task?.origin === "ft-05" && f.task?.reuse === false, "FT-05 DPO fehlt + FLAG_PERSONAL_DATA → Lücke + neue Aufgabe");
|
|
// Kein FT-05, wenn DPO gesetzt:
|
|
ok(!byCode({ ...base, personalData: true }, "FT-05"), "FT-05 nicht, wenn DPO benannt");
|
|
// Kein FT-05, wenn keine personenbezogenen Daten:
|
|
ok(!byCode({ ...base, roles: { ...base.roles, DPO: "" } }, "FT-05"), "FT-05 nicht ohne FLAG_PERSONAL_DATA");
|
|
}
|
|
|
|
// — FT-02: interner ISB (nicht IT) → schwacher Hinweis, keine Aufgabe —
|
|
{
|
|
const f = byCode({ ...base, isbInternal: true }, "FT-02");
|
|
ok(!!f && f.severity === "schwach" && !f.task, "FT-02 interner ISB → Hinweis ohne Aufgabe");
|
|
}
|
|
|
|
// — FT-06 immer vorhanden (manuell) —
|
|
ok(!!byCode(base, "FT-06") && !byCode(base, "FT-06")!.task, "FT-06 immer vorhanden, ohne Aufgabe");
|
|
|
|
console.log(failures === 0 ? "\nOK — alle FT-Tests grün" : `\nPRUEFEN — ${failures} Fehler`);
|
|
process.exit(failures === 0 ? 0 : 1);
|