Iteration 2: Assets & BIA als gemeinsames Modul
- App-Shell mit Seitennavigation (alle 12 Module, kommende ausgegraut), shadcn/ui-Setup (Base-UI-Variante) mit hellem Theme - Asset-Inventar: filterbare Liste (Suche/Typ/Status), Anlegen/Bearbeiten/ Löschen, Detailansicht mit Schutzbedarf (C/I/A 1–4), Abhängigkeiten (beide Richtungen, hinzufügen/entfernen), zugeordneten Prozessen mit Primär-/Sekundär-Rolle und Platzhalter für zugeordnete Risiken - Prozesse & BIA: Liste mit Kritikalität/RTO/MTD, Prozess-Detail mit Asset-Zuordnung nach Rolle (primär/sekundär), BIA-Formular (RTO/RPO/MTD, Schadenshöhe je Schutzziel, Kritikalität nach Max-Prinzip) - Server-Actions mit Zod-Validierung, requirePermission und Audit-Log für jede schreibende Aktion; Tenant-Guard um upsert-Injektion erweitert - Prisma: Asset, AssetRelation, Process, ProcessAsset, BiaEntry inkl. RLS-Policies; Seed mit Beispiel-Assets, Prozessen und BIA - Im Browser verifiziert: CRUD, Relationen, BIA-Speichern, Audit-Einträge Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+128
-2
@@ -56,8 +56,10 @@ model User {
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
userRoles UserRole[]
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
userRoles UserRole[]
|
||||
ownedAssets Asset[] @relation("assetOwner")
|
||||
ownedProcesses Process[] @relation("processOwner")
|
||||
|
||||
@@unique([tenantId, email])
|
||||
@@index([tenantId])
|
||||
@@ -110,6 +112,130 @@ model RolePermission {
|
||||
@@map("role_permissions")
|
||||
}
|
||||
|
||||
// ── Assets & BIA (ein Modul, SPEC §4.1) ─────────────────────────────────────
|
||||
|
||||
enum AssetType {
|
||||
INFORMATION
|
||||
SYSTEM
|
||||
APPLICATION
|
||||
LOCATION
|
||||
SUPPLIER
|
||||
PERSON
|
||||
DATA
|
||||
}
|
||||
|
||||
enum AssetStatus {
|
||||
ACTIVE
|
||||
PLANNED
|
||||
RETIRED
|
||||
}
|
||||
|
||||
enum ProcessAssetRole {
|
||||
PRIMARY
|
||||
SECONDARY
|
||||
}
|
||||
|
||||
model Asset {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
name String
|
||||
description String?
|
||||
type AssetType
|
||||
status AssetStatus @default(ACTIVE)
|
||||
ownerId String? @map("owner_id")
|
||||
location String?
|
||||
tags String[] @default([])
|
||||
// Schutzbedarf 1–4 je Schutzziel (C/I/A)
|
||||
confidentiality Int @default(1)
|
||||
integrity Int @default(1)
|
||||
availability Int @default(1)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
createdBy String? @map("created_by")
|
||||
|
||||
owner User? @relation("assetOwner", fields: [ownerId], references: [id])
|
||||
relationsFrom AssetRelation[] @relation("relationFrom")
|
||||
relationsTo AssetRelation[] @relation("relationTo")
|
||||
processAssets ProcessAsset[]
|
||||
|
||||
@@index([tenantId])
|
||||
@@index([tenantId, type])
|
||||
@@map("assets")
|
||||
}
|
||||
|
||||
model AssetRelation {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
assetId String @map("asset_id")
|
||||
relatedAssetId String @map("related_asset_id")
|
||||
// z. B. depends_on, hosts, processes_data_of
|
||||
type String @default("depends_on")
|
||||
|
||||
asset Asset @relation("relationFrom", fields: [assetId], references: [id], onDelete: Cascade)
|
||||
relatedAsset Asset @relation("relationTo", fields: [relatedAssetId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([assetId, relatedAssetId, type])
|
||||
@@index([tenantId])
|
||||
@@map("asset_relations")
|
||||
}
|
||||
|
||||
model Process {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
name String
|
||||
description String?
|
||||
ownerId String? @map("owner_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
createdBy String? @map("created_by")
|
||||
|
||||
owner User? @relation("processOwner", fields: [ownerId], references: [id])
|
||||
processAssets ProcessAsset[]
|
||||
bia BiaEntry?
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("processes")
|
||||
}
|
||||
|
||||
model ProcessAsset {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
processId String @map("process_id")
|
||||
assetId String @map("asset_id")
|
||||
role ProcessAssetRole @default(SECONDARY)
|
||||
|
||||
process Process @relation(fields: [processId], references: [id], onDelete: Cascade)
|
||||
asset Asset @relation(fields: [assetId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([processId, assetId])
|
||||
@@index([tenantId])
|
||||
@@map("process_assets")
|
||||
}
|
||||
|
||||
model BiaEntry {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
processId String @unique @map("process_id")
|
||||
// Wiederanlaufparameter in Stunden (SPEC §4.1.2)
|
||||
rtoHours Int? @map("rto_hours")
|
||||
rpoHours Int? @map("rpo_hours")
|
||||
mtdHours Int? @map("mtd_hours")
|
||||
// Schadenshöhe 1–4 je Schutzziel
|
||||
impactC Int @default(1) @map("impact_c")
|
||||
impactI Int @default(1) @map("impact_i")
|
||||
impactA Int @default(1) @map("impact_a")
|
||||
// Kritikalität 1–4, abgeleitet (Max-Prinzip), redundant gespeichert für Listen/Filter
|
||||
criticality Int @default(1)
|
||||
notes String?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
process Process @relation(fields: [processId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId])
|
||||
@@map("bia_entries")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
|
||||
Reference in New Issue
Block a user