Files
craftvia/scripts/test-scope-filter.ts
msolarczekandClaude Opus 5 c8e6f30a27
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s
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>
2026-09-14 11:05:39 +02:00

73 lines
4.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Akzeptanztest des Scope-Filters (Story A2-2). Repräsentative C1-Zeilen + Scope-
// Dynamik. Reine Logik, kein DB-Zugriff. Lauf: npx tsx scripts/test-scope-filter.ts
import { C1_ROWS, activeRequirements, isRequirementActive, scopeSummary, type Pruefziel } from "../src/lib/scope-filter";
let failures = 0;
const ok = (cond: boolean, msg: string) => {
console.log(`${cond ? "✓" : "✗ FEHLER"} ${msg}`);
if (!cond) failures++;
};
const row = (id: string) => {
const r = C1_ROWS.find((x) => x.id === id);
if (!r) throw new Error(`C1-Zeile ${id} nicht gefunden`);
return r;
};
// Flag-Sets: HIGH ist AL2-Baseline, VERY_HIGH nur AL3 (A2-1).
const AL2 = { FLAG_HIGH_PROTECTION: true, FLAG_VERY_HIGH_PROTECTION: false, FLAG_ELEVATED_PROTECTION: true };
const AL3 = { FLAG_HIGH_PROTECTION: true, FLAG_VERY_HIGH_PROTECTION: true, FLAG_ELEVATED_PROTECTION: true };
const SHOULD = { FLAG_INCLUDE_SHOULD: true };
const IS: Pruefziel[] = ["informationssicherheit"];
// — Grunddaten —
ok(C1_ROWS.length === 412, `C1-Datengrundlage: 412 Anforderungen (${C1_ROWS.length})`);
// — MUSS (immer im Scope) —
ok(isRequirementActive(row("1.1.1-M1"), { pruefziele: IS, flags: {} }), "1.1.1-M1 (MUSS) → im Scope ohne Flags");
// — SOLL nur bei FLAG_INCLUDE_SHOULD —
ok(!isRequirementActive(row("1.1.1-S1"), { pruefziele: IS, flags: { ...AL2 } }), "1.1.1-S1 (SOLL) → NICHT ohne FLAG_INCLUDE_SHOULD");
ok(isRequirementActive(row("1.1.1-S1"), { pruefziele: IS, flags: { ...AL2, ...SHOULD } }), "1.1.1-S1 (SOLL) → im Scope mit FLAG_INCLUDE_SHOULD");
// — HOCH nur bei FLAG_HIGH_PROTECTION —
ok(!isRequirementActive(row("1.2.2-H1"), { pruefziele: IS, flags: { FLAG_HIGH_PROTECTION: false } }), "1.2.2-H1 (HOCH) → NICHT ohne FLAG_HIGH_PROTECTION");
ok(isRequirementActive(row("1.2.2-H1"), { pruefziele: IS, flags: { ...AL2 } }), "1.2.2-H1 (HOCH) → im Scope bei AL2 (HIGH-Baseline)");
// — SEHR HOCH nur bei FLAG_VERY_HIGH_PROTECTION (AL3) —
ok(!isRequirementActive(row("1.3.4-V1"), { pruefziele: IS, flags: { ...AL2 } }), "1.3.4-V1 (SEHR HOCH) → NICHT bei AL2");
ok(isRequirementActive(row("1.3.4-V1"), { pruefziele: IS, flags: { ...AL3 } }), "1.3.4-V1 (SEHR HOCH) → im Scope bei AL3");
// — Kapitel 8.x nur bei Prüfziel Prototypenschutz —
ok(!isRequirementActive(row("8.1.1-M1"), { pruefziele: IS, flags: { ...AL3, ...SHOULD } }), "8.1.1-M1 → NICHT ohne Prüfziel Prototypenschutz");
ok(isRequirementActive(row("8.1.1-M1"), { pruefziele: [...IS, "prototypenschutz"], flags: {} }), "8.1.1-M1 → im Scope bei Prüfziel Prototypenschutz");
// — Kapitel 9.x nur bei Prüfziel Datenschutz —
ok(!isRequirementActive(row("9.1.1-M1"), { pruefziele: IS, flags: { ...AL3, ...SHOULD } }), "9.1.1-M1 → NICHT ohne Prüfziel Datenschutz");
ok(isRequirementActive(row("9.1.1-M1"), { pruefziele: [...IS, "datenschutz"], flags: {} }), "9.1.1-M1 → im Scope bei Prüfziel Datenschutz");
// — Scope-Dynamik (Kennzahlen) —
const al2 = scopeSummary({ pruefziele: IS, flags: { ...AL2, ...SHOULD } });
const al3 = scopeSummary({ pruefziele: IS, flags: { ...AL3, ...SHOULD } });
ok(al3.total > al2.total, `AL3 hat mehr Anforderungen als AL2 (${al3.total} > ${al2.total}) — SEHR HOCH kommt hinzu`);
ok(al3.total - al2.total === al3.byType["SEHR HOCH"], "AL3−AL2 == Anzahl SEHR HOCH (nur SEHR HOCH unterscheidet sich)");
const noShould = scopeSummary({ pruefziele: IS, flags: { ...AL2 } });
ok(al2.total - noShould.total === al2.byType.SOLL, "FLAG_INCLUDE_SHOULD schaltet genau die SOLL-Anforderungen");
const withProto = scopeSummary({ pruefziele: [...IS, "prototypenschutz"], flags: { ...AL3, ...SHOULD } });
ok(withProto.total > al3.total, `Prüfziel Prototypenschutz erhöht den Scope (${withProto.total} > ${al3.total})`);
ok((withProto.byPruefziel["prototypenschutz"] ?? 0) > 0 && !al3.byPruefziel["prototypenschutz"], "Prototyp-Anforderungen nur bei aktivem Prüfziel");
// — Volles Prüfziel-/Flag-Set = alle 412 —
const all = scopeSummary({ pruefziele: ["informationssicherheit", "prototypenschutz", "datenschutz"], flags: { ...AL3, ...SHOULD } });
ok(all.total === 412, `alle Prüfziele + AL3 + SOLL → alle 412 Anforderungen im Scope (${all.total})`);
// — Nur MUSS (keine Flags, nur IS) —
const mussOnly = activeRequirements({ pruefziele: IS, flags: {} });
ok(mussOnly.every((r) => r.type === "MUSS"), "ohne Flags/Zusatz-Prüfziele → nur MUSS (IS)");
console.log(failures === 0 ? "\nOK — alle Scope-Filter-Tests grün" : `\nPRUEFEN — ${failures} Fehler`);
process.exit(failures === 0 ? 0 : 1);