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>
117 lines
3.7 KiB
TypeScript
117 lines
3.7 KiB
TypeScript
/**
|
|
* Zentrale Konstanten/Helfer für das Modul „Vorfälle" (client-safe).
|
|
* Kategorien (§4-Taxonomie), Status (§3-Lebenszyklus) und die refNo-Anzeige.
|
|
*/
|
|
import type { IncidentSeverity } from "@/lib/incident-severity";
|
|
|
|
export const INCIDENT_CATEGORIES = [
|
|
"malware",
|
|
"phishing",
|
|
"unauthorized_access",
|
|
"data_loss",
|
|
"outage",
|
|
"physical",
|
|
"misconfiguration",
|
|
"supplier",
|
|
"prototype_customer_data",
|
|
"other",
|
|
] as const;
|
|
export type IncidentCategory = (typeof INCIDENT_CATEGORIES)[number];
|
|
|
|
export const INCIDENT_STATUSES = [
|
|
"neu",
|
|
"triage",
|
|
"in_bearbeitung",
|
|
"eingedaemmt",
|
|
"behoben",
|
|
"abgeschlossen",
|
|
"wiedereroeffnet",
|
|
] as const;
|
|
export type IncidentStatus = (typeof INCIDENT_STATUSES)[number];
|
|
|
|
export const INCIDENT_SOURCES = ["manual", "email"] as const;
|
|
export type IncidentSource = (typeof INCIDENT_SOURCES)[number];
|
|
|
|
export const INCIDENT_PRIORITIES = ["niedrig", "mittel", "hoch", "kritisch"] as const;
|
|
|
|
/**
|
|
* Erlaubte Statusübergänge (§3). Jeder Übergang wird serverseitig geprüft;
|
|
* bestimmte Übergänge verlangen zusätzlich Pflichtfelder (siehe TRANSITION_REQUIRES).
|
|
*/
|
|
export const STATUS_TRANSITIONS: Record<IncidentStatus, IncidentStatus[]> = {
|
|
neu: ["triage", "in_bearbeitung"],
|
|
triage: ["in_bearbeitung", "eingedaemmt"],
|
|
in_bearbeitung: ["eingedaemmt", "behoben"],
|
|
eingedaemmt: ["behoben", "in_bearbeitung"],
|
|
behoben: ["abgeschlossen", "wiedereroeffnet"],
|
|
abgeschlossen: ["wiedereroeffnet"],
|
|
wiedereroeffnet: ["triage", "in_bearbeitung"],
|
|
};
|
|
|
|
/**
|
|
* Pflichtfelder je Zielstatus (§8). Ein Übergang nach „behoben" verlangt Ursache +
|
|
* Lösung; „abgeschlossen" zusätzlich Abschlussnotiz + Lessons Learned.
|
|
*/
|
|
export const TRANSITION_REQUIRES: Partial<Record<IncidentStatus, string[]>> = {
|
|
behoben: ["rootCause", "resolution"],
|
|
abgeschlossen: ["rootCause", "resolution", "closingNote", "lessonsLearned"],
|
|
};
|
|
|
|
export function canTransition(from: IncidentStatus, to: IncidentStatus): boolean {
|
|
return STATUS_TRANSITIONS[from]?.includes(to) ?? false;
|
|
}
|
|
|
|
/**
|
|
* Ob der Nutzer vertrauliche Vorfälle sehen darf (§11): nur Rollen mit
|
|
* incident:manage oder incident:close. Der owner sieht seine eigenen zusätzlich
|
|
* über den ownerId-Filter (serverseitig in der Liste). Pure/client-safe.
|
|
*/
|
|
export function canSeeRestricted(session: { user?: { permissions?: string[] } }): boolean {
|
|
const p = session.user?.permissions ?? [];
|
|
return p.includes("incident:manage") || p.includes("incident:close");
|
|
}
|
|
|
|
/**
|
|
* Fehlende Pflichtfelder für einen Zielstatus (§8). Prüft die effektiven Werte
|
|
* (bereits gesetzt oder beim Übergang mitgeliefert). Leeres Array = alles erfüllt.
|
|
* Pure Funktion — von Action und Test gemeinsam genutzt.
|
|
*/
|
|
export function missingRequiredFields(
|
|
target: IncidentStatus,
|
|
values: Record<string, unknown>,
|
|
): string[] {
|
|
const required = TRANSITION_REQUIRES[target] ?? [];
|
|
return required.filter((field) => {
|
|
const v = values[field];
|
|
return v === null || v === undefined || (typeof v === "string" && v.trim() === "");
|
|
});
|
|
}
|
|
|
|
/** Farb-Ton (mockup-ui Pill) je Severity. */
|
|
export const SEVERITY_TONE: Record<IncidentSeverity, "mut" | "info" | "warn" | "risk"> = {
|
|
niedrig: "mut",
|
|
mittel: "info",
|
|
hoch: "warn",
|
|
kritisch: "risk",
|
|
};
|
|
|
|
/** Farb-Ton je Status. */
|
|
export const STATUS_TONE: Record<IncidentStatus, "mut" | "info" | "warn" | "risk" | "ok"> = {
|
|
neu: "risk",
|
|
triage: "warn",
|
|
in_bearbeitung: "info",
|
|
eingedaemmt: "info",
|
|
behoben: "ok",
|
|
abgeschlossen: "mut",
|
|
wiedereroeffnet: "warn",
|
|
};
|
|
|
|
/** Farb-Ton je Meldung-Track-Status (reportStatus, §3 Parallel-Track). */
|
|
export const REPORT_STATUS_TONE: Record<string, "mut" | "info" | "warn" | "orange" | "ok"> = {
|
|
none: "mut",
|
|
pruefung: "warn",
|
|
erstmeldung: "orange",
|
|
folgemeldung: "info",
|
|
abschluss: "ok",
|
|
};
|