Files
IPAM/ARCHITECTURE.md
Mathieu BOURBON fbb6138c28 first commit
2026-04-18 16:24:44 +02:00

148 lines
7.1 KiB
Markdown

# Architecture
Ce document décrit la structure du projet et les principes qui la gouvernent,
afin de garder l'application **évolutive** (facile à étendre, sans dette).
## Principes
1. **Modular monolith** — un seul projet Next.js, mais des modules métier isolés
sous `src/modules/<domaine>/`. Chaque module expose son `service` ; les routes
API et l'UI n'accèdent JAMAIS directement à Prisma pour un domaine.
2. **Validation à la frontière** — tout input externe (API, formulaire, scanner)
est validé via un schéma Zod avant d'atteindre le service.
3. **Registry pattern** pour les scanners — ajouter une capacité de découverte se
fait en implémentant une interface `Scanner` et en l'enregistrant dans le
registre (aucune autre partie du code n'est touchée).
4. **DB-agnostic** — Prisma lit `DATABASE_PROVIDER` et `DATABASE_URL` à l'exécution ;
SQLite pour commencer, PostgreSQL plus tard sans refactor.
## Arborescence
```
IPAM/
├── docker/ Dockerfile + docker-compose (profils sqlite/postgres)
├── prisma/
│ ├── schema.prisma Modèle de données (Network, Host, Port, Application, Scan)
│ ├── migrations/ Migrations SQL (créées par `db:migrate`)
│ └── seed.ts Données d'exemple
├── public/ Assets statiques
├── scripts/
│ └── run-discovery.ts CLI pour lancer une découverte hors UI
├── src/
│ ├── app/ Next.js App Router
│ │ ├── (dashboard)/ Route group → layout UI commun (sidebar, header)
│ │ │ ├── hosts/ Pages de gestion des hôtes
│ │ │ ├── networks/
│ │ │ ├── applications/
│ │ │ ├── scans/
│ │ │ └── settings/
│ │ ├── api/ Route Handlers — FINS, délèguent aux services
│ │ │ ├── hosts/
│ │ │ ├── networks/
│ │ │ ├── applications/
│ │ │ ├── ports/
│ │ │ ├── scans/
│ │ │ └── discovery/
│ │ ├── layout.tsx
│ │ └── page.tsx
│ │
│ ├── components/ Composants React
│ │ ├── ui/ Primitives (Button, Input, Dialog...)
│ │ ├── layout/ Sidebar, Header, Shell
│ │ ├── hosts/ networks/ ... Composants spécifiques par domaine
│ │ └── common/ Composants réutilisables (DataTable, Skeleton...)
│ │
│ ├── modules/ ★ Cœur métier — UN DOSSIER PAR DOMAINE
│ │ ├── hosts/
│ │ │ ├── hosts.schema.ts Validation Zod + types
│ │ │ ├── hosts.repository.ts Accès Prisma (seule frontière avec la DB)
│ │ │ ├── hosts.service.ts Logique métier
│ │ │ └── index.ts
│ │ ├── networks/
│ │ ├── applications/
│ │ ├── ports/
│ │ ├── scans/
│ │ └── discovery/ ★ Découverte réseau (pluggable)
│ │ ├── types.ts Interface `Scanner` + types résultats
│ │ ├── registry.ts Enregistrement des scanners
│ │ ├── discovery.service.ts Orchestrateur (persiste en DB)
│ │ ├── scanners/
│ │ │ ├── ping.scanner.ts
│ │ │ ├── port.scanner.ts
│ │ │ ├── arp.scanner.ts
│ │ │ └── mdns.scanner.ts
│ │ └── utils/
│ │ └── concurrency.ts Runner parallèle borné
│ │
│ ├── lib/ Utilitaires transverses
│ │ ├── db/prisma.ts Client Prisma (singleton)
│ │ ├── api/response.ts Helpers NextResponse (ok/badRequest/...)
│ │ ├── utils/cn.ts Merge classes Tailwind
│ │ └── utils/logger.ts Pino logger configuré
│ │
│ ├── config/env.ts Env vars typées via Zod (fail-fast)
│ ├── hooks/ Hooks React partagés (ex: useHosts)
│ ├── types/ Types globaux
│ └── styles/globals.css Tailwind + variables de thème
├── tests/ Unitaires + intégration (vitest)
├── .env.example
├── next.config.mjs output: standalone + ext pkgs réseau
├── tsconfig.json Aliases @/modules, @/lib, @/components…
└── tailwind.config.ts
```
## Flux d'une requête
```
Client (RSC ou fetch)
→ src/app/api/<domaine>/route.ts (validation + handleError)
→ src/modules/<domaine>/service.ts (règles métier)
→ src/modules/<domaine>/repository (Prisma)
→ DB (SQLite | PostgreSQL)
```
## Ajouter un module métier (ex: VLAN)
1. Créer `src/modules/vlans/` avec `vlans.schema.ts`, `vlans.service.ts`, `index.ts`
2. Ajouter le modèle Prisma dans `prisma/schema.prisma``npm run db:migrate`
3. Créer les routes `src/app/api/vlans/route.ts` (et `[id]/route.ts`) — copier le pattern des hôtes
4. Créer la page `src/app/(dashboard)/vlans/page.tsx`
5. (Optionnel) Ajouter des composants UI dans `src/components/vlans/`
Aucun fichier existant ne doit être modifié en dehors de `schema.prisma`.
## Ajouter un scanner de découverte (ex: SNMP)
1. Créer `src/modules/discovery/scanners/snmp.scanner.ts` exportant une constante
conforme à l'interface `Scanner` (`kind`, `label`, `enabled`, `run`)
2. L'importer dans `src/modules/discovery/registry.ts` et l'ajouter au
`scannersRegistry` avec sa clé `ScannerKind` (mettre à jour le type union dans
`types.ts`)
3. Exposer la clé dans `bodySchema` de `src/app/api/discovery/route.ts`
Il sera automatiquement disponible dans `runSingle()` et, si intégré à
`runFull()`, dans le scan complet.
## Choix techniques clefs
- **Prisma plutôt que Drizzle** : meilleures migrations pour un homelab, Studio
inclus. Drizzle serait envisageable plus tard si on a besoin de SQL brut.
- **App Router (pas Pages Router)** : server components, streaming, server
actions disponibles quand on voudra simplifier des formulaires.
- **Pas de framework "d'auth" pour l'instant** : ajouter NextAuth/Auth.js quand
on exposera l'IPAM au-delà du LAN. Un emplacement naturel : `src/modules/auth/`.
- **Pas de Redis/queue** : tous les scans tournent dans le process. À prévoir
(BullMQ + Redis) uniquement si on planifie des scans récurrents lourds.
## Futures fonctionnalités envisagées
- Scans planifiés (cron-like, via BullMQ ou `node-cron`)
- Notifications (nouvel hôte, port qui change d'état)
- Export CSV / JSON des inventaires
- Synchronisation avec un reverse-proxy (Traefik, Nginx Proxy Manager) pour
auto-remplir les applications
- API d'OUI lookup pour déduire le constructeur depuis la MAC
- Authentification multi-utilisateur + RBAC
- Topologie graphique (D3 ou React Flow)