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>
195 lines
6.3 KiB
Plaintext
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])
|
|
}
|