Initial commit: bootstrap monorepo NetMapper
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
.vite/
|
||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
coverage/
|
||||||
|
.pytest_cache/
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# NetMapper2026
|
||||||
|
|
||||||
|
NetMapper è una web app self-hosted per la mappatura dinamica di un homelab su più livelli: fisico, logico, gerarchico e inventario/IP.
|
||||||
|
|
||||||
|
## Obiettivi iniziali
|
||||||
|
|
||||||
|
- Discovery di rete multi-livello con granularitਨ.
|
||||||
|
- Modellazione gerarchica di host fisici, VM, container, app e dispositivi di rete.
|
||||||
|
- Associazione IP/MAC/interfacce agli oggetti mappati.
|
||||||
|
- Vista fisica e logica editabile, con arricchimento manuale.
|
||||||
|
- Deploy semplice in LXC Proxmox con base portabile verso Docker/Podman.
|
||||||
|
|
||||||
|
## Monorepo layout
|
||||||
|
|
||||||
|
- `docs/` - visione, modello dati, roadmap e scelte architetturali.
|
||||||
|
- `frontend/` - UI web dell'applicazione.
|
||||||
|
- `backend/` - API, logica dominio e persistenza.
|
||||||
|
- `worker/` - motore di discovery e job asincroni.
|
||||||
|
- `deploy/` - file di deploy, compose e containerizzazione.
|
||||||
|
|
||||||
|
## MVP
|
||||||
|
|
||||||
|
1. CRUD oggetti, IP, interfacce e relazioni.
|
||||||
|
2. Discovery base subnet/host/porte.
|
||||||
|
3. Discovery SNMP/LLDP per topologia iniziale.
|
||||||
|
4. Mappa visuale con nodi annidati e pannello dettagli.
|
||||||
|
|
||||||
|
## Stack proposto
|
||||||
|
|
||||||
|
- Frontend: React + TypeScript + Vite
|
||||||
|
- Backend: FastAPI
|
||||||
|
- Worker discovery: Python
|
||||||
|
- Database: PostgreSQL
|
||||||
|
- Cache/queue: Redis
|
||||||
|
- Deploy: Docker Compose
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Domain Model
|
||||||
|
|
||||||
|
## Entitਨ principali
|
||||||
|
|
||||||
|
### Object
|
||||||
|
Rappresenta qualsiasi entitਨ mappabile.
|
||||||
|
|
||||||
|
Campi iniziali:
|
||||||
|
- `id`
|
||||||
|
- `name`
|
||||||
|
- `slug`
|
||||||
|
- `type` (`site`, `area`, `rack`, `physical_host`, `vm`, `lxc`, `app`, `switch`, `firewall`, `router`, `ap`, `camera`, `storage`, `other`)
|
||||||
|
- `status`
|
||||||
|
- `vendor`
|
||||||
|
- `model`
|
||||||
|
- `serial`
|
||||||
|
- `os_name`
|
||||||
|
- `os_version`
|
||||||
|
- `notes`
|
||||||
|
|
||||||
|
### ObjectRelation
|
||||||
|
Relazione tra due oggetti.
|
||||||
|
|
||||||
|
Campi iniziali:
|
||||||
|
- `id`
|
||||||
|
- `source_object_id`
|
||||||
|
- `target_object_id`
|
||||||
|
- `relation_type` (`contains`, `hosts`, `connected_to`, `depends_on`, `managed_by`, `runs`)
|
||||||
|
- `confidence`
|
||||||
|
- `source_type` (`manual`, `nmap`, `snmp`, `lldp`, `arp`, `api`)
|
||||||
|
|
||||||
|
### NetworkInterface
|
||||||
|
Interfaccia di rete collegata a un oggetto.
|
||||||
|
|
||||||
|
Campi iniziali:
|
||||||
|
- `id`
|
||||||
|
- `object_id`
|
||||||
|
- `name`
|
||||||
|
- `mac_address`
|
||||||
|
- `mtu`
|
||||||
|
- `speed`
|
||||||
|
- `admin_state`
|
||||||
|
- `oper_state`
|
||||||
|
- `description`
|
||||||
|
|
||||||
|
### IPAddress
|
||||||
|
Indirizzo IP associato a un oggetto o a un'interfaccia.
|
||||||
|
|
||||||
|
Campi iniziali:
|
||||||
|
- `id`
|
||||||
|
- `address`
|
||||||
|
- `version`
|
||||||
|
- `prefix_length`
|
||||||
|
- `hostname`
|
||||||
|
- `dns_name`
|
||||||
|
- `status`
|
||||||
|
- `object_id`
|
||||||
|
- `interface_id`
|
||||||
|
- `is_primary`
|
||||||
|
- `source_type`
|
||||||
|
|
||||||
|
### DiscoveryJob
|
||||||
|
Esecuzione di un task di discovery.
|
||||||
|
|
||||||
|
Campi iniziali:
|
||||||
|
- `id`
|
||||||
|
- `job_type`
|
||||||
|
- `scope`
|
||||||
|
- `status`
|
||||||
|
- `started_at`
|
||||||
|
- `finished_at`
|
||||||
|
- `requested_by`
|
||||||
|
- `parameters_json`
|
||||||
|
- `result_summary`
|
||||||
|
|
||||||
|
### Evidence
|
||||||
|
Dato grezzo o semi-normalizzato raccolto da una sorgente.
|
||||||
|
|
||||||
|
Campi iniziali:
|
||||||
|
- `id`
|
||||||
|
- `source_type`
|
||||||
|
- `object_hint`
|
||||||
|
- `payload_json`
|
||||||
|
- `observed_at`
|
||||||
|
- `fingerprint`
|
||||||
|
|
||||||
|
## Nota di progettazione
|
||||||
|
|
||||||
|
Separare oggetti, relazioni e evidenze consente di distinguere ciò che il sistema ha osservato da ciò che il sistema ha consolidato nel modello finale.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# MVP Roadmap
|
||||||
|
|
||||||
|
## Fase 0 - Fondazioni
|
||||||
|
- Inizializzare monorepo.
|
||||||
|
- Definire modello dati iniziale.
|
||||||
|
- Preparare stack locale con Postgres e Redis.
|
||||||
|
|
||||||
|
## Fase 1 - Inventario manuale
|
||||||
|
- CRUD oggetti.
|
||||||
|
- CRUD IP e interfacce.
|
||||||
|
- Relazioni padre/figlio e connected_to.
|
||||||
|
|
||||||
|
## Fase 2 - Discovery base
|
||||||
|
- Scan subnet configurate.
|
||||||
|
- Host attivi, porte base, reverse DNS.
|
||||||
|
- Prima normalizzazione in inventario.
|
||||||
|
|
||||||
|
## Fase 3 - Discovery arricchita
|
||||||
|
- SNMP read-only.
|
||||||
|
- Neighbor LLDP/CDP.
|
||||||
|
- MAC table e inferenza link.
|
||||||
|
|
||||||
|
## Fase 4 - UI mappa
|
||||||
|
- Vista grafo iniziale.
|
||||||
|
- Contenitori annidati.
|
||||||
|
- Pannello dettagli per oggetto/IP.
|
||||||
|
|
||||||
|
## Fase 5 - Connettori homelab
|
||||||
|
- Proxmox.
|
||||||
|
- Docker/Podman.
|
||||||
|
- Eventuali import futuri da altri sistemi.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Vision
|
||||||
|
|
||||||
|
NetMapper nasce per diventare il punto centrale di osservazione e documentazione di un homelab.
|
||||||
|
|
||||||
|
L'applicazione deve unire discovery automatico e modellazione manuale, perché la topologia reale non è sempre deducibile in modo completo dal solo scanning di rete. Il risultato atteso non è solo un inventario di IP, ma una mappa navigabile che rappresenti relazioni, contenimento, collegamenti e contesto operativo.
|
||||||
|
|
||||||
|
## Viste principali
|
||||||
|
|
||||||
|
- Vista fisica: switch, firewall, server, access point, modem, telecamere e collegamenti.
|
||||||
|
- Vista logica: subnet, VLAN, servizi esposti, flussi e dipendenze.
|
||||||
|
- Vista gerarchica: host fisico > VM/LXC > app/servizi.
|
||||||
|
- Vista inventario/IP: indirizzi, MAC, interfacce, metadati, note e sorgenti discovery.
|
||||||
|
|
||||||
|
## Principi
|
||||||
|
|
||||||
|
- Source of truth interna, ma alimentata da discovery.
|
||||||
|
- Ogni informazione deve avere origine, timestamp e livello di confidenza.
|
||||||
|
- Nessun lock-in sul runtime: deve girare bene sia in LXC sia in container.
|
||||||
|
- Plugin/connettori per estendere discovery e import dati.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="it">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>NetMapper</title>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "netmapper-frontend",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.1.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.6.2",
|
||||||
|
"vite": "^5.4.8",
|
||||||
|
"@vitejs/plugin-react": "^4.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom/client'
|
||||||
|
import { App } from './pages/App'
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
export function App() {
|
||||||
|
return (
|
||||||
|
<main style={{ fontFamily: 'sans-serif', padding: '2rem' }}>
|
||||||
|
<h1>NetMapper</h1>
|
||||||
|
<p>Bootstrap iniziale della UI.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Topology view</li>
|
||||||
|
<li>Inventory view</li>
|
||||||
|
<li>IP registry</li>
|
||||||
|
<li>Discovery jobs</li>
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"allowImportingTsExtensions": false,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user