import { readFileSync, readdirSync, statSync } from "node:fs"; import path from "node:path"; import { describe, expect, it } from "vitest"; /** * Strukturell (#006): Nur der Worker liest Chiffrat und Data-Key, und der Webprozess * importiert nichts aus src/worker – sonst laege der Master-Key-Zugriff im Web. */ function dateien(verzeichnis: string): string[] { return readdirSync(verzeichnis).flatMap((name) => { const pfad = path.join(verzeichnis, name); if (statSync(pfad).isDirectory()) return name === "generated" ? [] : dateien(pfad); return /\.(ts|tsx)$/.test(name) ? [pfad.split(path.sep).join("/")] : []; }); } const ALLE = dateien("src"); /** Dateien, die die Namen tragen, ohne die Datenbank zu lesen – mit Begruendung. */ const NAMEN_ERLAUBT: Record = { "src/worker/geheimnisse.ts": "die eine Stelle, die liest", "src/lib/krypto/umschlag.ts": "Feldname des Umschlags, rein rechnerisch", "src/lib/protokoll-schwaerzen.ts": "Feldname in der Schwaerz-Liste", }; describe("Grenze um die Private Keys", () => { it("nur src/worker/geheimnisse.ts liest privatVerschluesselt und dekVerschluesselt", () => { const verstoesse = ALLE.filter( (datei) => !NAMEN_ERLAUBT[datei] && /privatVerschluesselt|dekVerschluesselt/.test(readFileSync(datei, "utf8")), ); expect(verstoesse).toEqual([]); }); it("nichts ausserhalb von src/worker importiert aus src/worker", () => { const verstoesse = ALLE.filter( (datei) => !datei.startsWith("src/worker/") && /from ["']@\/worker\//.test(readFileSync(datei, "utf8")), ); expect(verstoesse).toEqual([]); }); });