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,61 @@
|
||||
import "dotenv/config";
|
||||
import { prisma } from "../src/server/db";
|
||||
|
||||
/**
|
||||
* Backfill 5×5-Risikokriterien für Bestandsmandanten: ergänzt die 5. Eintritts-
|
||||
* wahrscheinlichkeits-Stufe und die 5. Schadensstufe je Dimension, falls noch nicht
|
||||
* vorhanden. Die Bewertung (Formular/Matrix/Score) war schon 5×5 — nur die Kriterien-
|
||||
* daten waren 4-stufig geseedet. Idempotent (mehrfach ausführbar).
|
||||
*
|
||||
* npx tsx scripts/backfill-risk-5x5.ts # alle Mandanten
|
||||
* TENANT_SLUG=gefim npx tsx scripts/backfill-risk-5x5.ts # nur einer
|
||||
*/
|
||||
|
||||
// Sinnvolle Default-Texte für Stufe 5 der Standard-Schadensdimensionen (Abgleich per Name).
|
||||
const LEVEL5: Record<string, string> = {
|
||||
"Gesetzes-/Vertragsverstöße": "existenzbedrohende Rechtsfolgen (Lizenzentzug/Haftung)",
|
||||
"Datenschutz": "besonders schützenswerte Daten in großem Umfang / existenzielle Betroffenheit",
|
||||
"Persönliche Unversehrtheit": "Lebensgefahr für viele / Todesfolge",
|
||||
"Aufgabenerfüllung": "vollständiger, dauerhafter Ausfall der Organisation",
|
||||
"Innen-/Außenwirkung (Reputation)": "existenzbedrohender, dauerhafter Reputationsverlust",
|
||||
"Störungs-/Ausfallzeit": "> 1 Monat / dauerhaft",
|
||||
"Finanzielle Auswirkungen": "existenzbedrohend (> 1 Mio €)",
|
||||
};
|
||||
const FALLBACK5 = "(bitte definieren)";
|
||||
|
||||
async function main() {
|
||||
const slug = process.env.TENANT_SLUG?.trim().toLowerCase();
|
||||
const tenants = await prisma.tenant.findMany({ where: slug ? { slug } : {}, select: { id: true, slug: true } });
|
||||
if (!tenants.length) { console.log("Keine Mandanten gefunden."); return; }
|
||||
|
||||
for (const t of tenants) {
|
||||
let ew5 = 0, dim5 = 0;
|
||||
|
||||
// EW-Stufe 5 ergänzen, falls nicht vorhanden
|
||||
const hasEw5 = await prisma.riskEwLevel.findFirst({ where: { tenantId: t.id, level: 5 } });
|
||||
if (!hasEw5) {
|
||||
// Nur ergänzen, wenn überhaupt EW-Stufen existieren (sonst provisioniert der Mandant sie neu).
|
||||
const anyEw = await prisma.riskEwLevel.count({ where: { tenantId: t.id } });
|
||||
if (anyEw > 0) {
|
||||
await prisma.riskEwLevel.create({ data: { tenantId: t.id, level: 5, label: "Nahezu sicher", definition: "Ereignis ist praktisch dauerhaft gegeben oder tritt ständig ein." } });
|
||||
ew5 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Schadensdimensionen: je Dimension "5" ergänzen, falls fehlt
|
||||
const dims = await prisma.riskDamageDimension.findMany({ where: { tenantId: t.id } });
|
||||
for (const d of dims) {
|
||||
const levels = (d.levels ?? {}) as Record<string, string>;
|
||||
if (levels["5"] == null || levels["5"] === "") {
|
||||
levels["5"] = LEVEL5[d.name] ?? FALLBACK5;
|
||||
await prisma.riskDamageDimension.update({ where: { id: d.id }, data: { levels } });
|
||||
dim5++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Mandant ${t.slug}: EW-Stufe 5 ${ew5 ? "ergänzt" : "bereits vorhanden/übersprungen"}, ${dim5} Schadensdimension(en) um Stufe 5 ergänzt.`);
|
||||
}
|
||||
console.log("Fertig.");
|
||||
}
|
||||
|
||||
main().then(() => process.exit(0)).catch((e) => { console.error(e); process.exit(1); });
|
||||
Reference in New Issue
Block a user