Files
IPAM/prisma/schema.prisma
Mathieu 2afb2e3bd2 fix(prisma): déclare les binaryTargets Alpine x64 et arm64
Sans binaryTargets explicites, Prisma ne génère l'engine que pour
la plateforme du builder, ce qui fait échouer le runtime sur les
containers Alpine arm64 (Raspberry Pi, Apple Silicon en émulation).
Ajout des cibles linux-musl-openssl-3.0.x et
linux-musl-arm64-openssl-3.0.x en plus de "native".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 14:22:09 +02:00

195 lines
6.3 KiB
Plaintext

// IPAM — Schéma Prisma
// ---------------------------------------------------------------------
// Prisma n'accepte PAS `env()` pour le champ `provider` (seulement pour `url`).
// Le provider par défaut est donc `sqlite`. Pour basculer vers PostgreSQL :
// npm run db:use-postgres
// puis régénérer le client : `npm run db:generate` et migrer : `npm run db:migrate`.
// Pour revenir à SQLite : `npm run db:use-sqlite`.
// ---------------------------------------------------------------------
generator client {
provider = "prisma-client-js"
// - native : dev local (macOS / Linux glibc)
// - linux-musl-openssl-3.0.x : runtime Alpine x86_64
// - linux-musl-arm64-openssl-3.0.x : runtime Alpine arm64 (Raspberry Pi, Apple Silicon en Docker, etc.)
binaryTargets = ["native", "linux-musl-openssl-3.0.x", "linux-musl-arm64-openssl-3.0.x"]
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
// =====================================================================
// Réseaux (subnets / VLAN)
// =====================================================================
model Network {
id String @id @default(cuid())
name String
cidr String @unique // ex: "192.168.1.0/24"
description String?
vlanId Int?
gateway String?
dnsServers String? // CSV — compat SQLite (pas de array natif)
color String? // Couleur d'affichage UI
hosts Host[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([cidr])
}
// =====================================================================
// Hôtes (une IP = un hôte)
// =====================================================================
model Host {
id String @id @default(cuid())
ipAddress String @unique // IPv4/IPv6
hostname String?
macAddress String?
description String?
vendor String? // Issue du MAC (OUI) ou d'une fingerprint
osGuess String? // OS détecté / renseigné
// Valeurs : "UP" | "DOWN" | "UNKNOWN" (validation Zod côté app)
status String @default("UNKNOWN")
// Origine de la fiche : "MANUAL" | "DISCOVERED" | "IMPORTED"
source String @default("MANUAL")
// Relations
networkId String?
network Network? @relation(fields: [networkId], references: [id], onDelete: SetNull)
ports Port[]
applications HostApplication[]
scanResults ScanResult[]
lastSeenAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([ipAddress])
@@index([networkId])
@@index([status])
}
// NOTE : les enums Prisma ne sont pas supportés par SQLite. On stocke
// donc tous les statuts/types en `String` et on valide les valeurs
// possibles côté app via Zod. Constantes documentées au-dessus de
// chaque champ.
// =====================================================================
// Ports ouverts sur un hôte
// =====================================================================
model Port {
id String @id @default(cuid())
number Int
// Valeurs : "TCP" | "UDP"
protocol String @default("TCP")
serviceName String? // ex: "http", "ssh", renseigné ou deviné
banner String? // Banner applicatif collecté
// Valeurs : "OPEN" | "CLOSED" | "FILTERED" | "UNKNOWN"
state String @default("OPEN")
hostId String
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
// Lien éventuel vers une application métier déclarée
applicationId String?
application Application? @relation(fields: [applicationId], references: [id], onDelete: SetNull)
lastCheckedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([hostId, number, protocol])
@@index([hostId])
@@index([number])
}
// Protocol : "TCP" | "UDP" — voir Port.protocol
// PortState : "OPEN" | "CLOSED" | "FILTERED" | "UNKNOWN" — voir Port.state
// =====================================================================
// Applications (Jellyfin, Home Assistant, Nextcloud, etc.)
// =====================================================================
model Application {
id String @id @default(cuid())
name String @unique
description String?
category String? // ex: "media", "monitoring", "storage"
icon String? // URL ou clé d'icône
url String? // URL principale d'accès
hosts HostApplication[]
ports Port[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// Table de jointure Hôte <-> Application (N:N)
model HostApplication {
hostId String
applicationId String
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)
notes String?
createdAt DateTime @default(now())
@@id([hostId, applicationId])
}
// =====================================================================
// Découverte réseau — historique des scans
// =====================================================================
model Scan {
id String @id @default(cuid())
// Valeurs : "PING" | "PORT" | "ARP" | "MDNS" | "FULL"
type String
// Valeurs : "PENDING" | "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED"
status String @default("PENDING")
target String // CIDR, IP, ou hôte
params String? // JSON (Zod validé côté app)
startedAt DateTime?
endedAt DateTime?
hostsFound Int @default(0)
portsFound Int @default(0)
errorMessage String?
results ScanResult[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([status])
@@index([type])
}
// ScanType : "PING" | "PORT" | "ARP" | "MDNS" | "FULL" — voir Scan.type
// ScanStatus : "PENDING" | "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED" — voir Scan.status
// Résultat individuel d'un scan (rattaché à un hôte quand possible)
model ScanResult {
id String @id @default(cuid())
scanId String
scan Scan @relation(fields: [scanId], references: [id], onDelete: Cascade)
ipAddress String
hostId String?
host Host? @relation(fields: [hostId], references: [id], onDelete: SetNull)
data String // JSON (ports trouvés, services mDNS, MAC, etc.)
createdAt DateTime @default(now())
@@index([scanId])
@@index([ipAddress])
}