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,116 @@
|
||||
/**
|
||||
* 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",
|
||||
};
|
||||
Reference in New Issue
Block a user