Application web d'inventaire réseau manuel avec FastAPI, Vue 3 et Docker. Inclut l'authentification JWT, la découverte ICMP, et la topologie en cards CSS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.0 KiB
Data Model
Schema Overview
users
id PK
username UNIQUE NOT NULL
hashed_password NOT NULL
vlans
id PK
vlan_id UNIQUE NULL ← NULL = plain LAN (no 802.1Q tag)
name NOT NULL
cidr NULL
color NULL
devices
id PK
name NOT NULL
type
description
is_gateway BOOL
is_livebox BOOL
virt_type NULL ← null | baremetal | lxc | qemu
url NULL
device_interfaces
id PK
device_id FK → devices.id NOT NULL
vlan_id FK → vlans.id NULL ← NULL = no network assignment
ip_address NULL
name
is_upstream BOOL
links
id PK
source_device_id FK → devices.id NOT NULL
target_device_id FK → devices.id NOT NULL
link_type
description
Relationships
Device1 → NDeviceInterface(cascade delete-orphan)Vlan1 → NDeviceInterface(nullable FK — deleting a VLAN setsvlan_idto NULL on its interfaces)LinkreferencesDevicetwice (source, target) — links are deleted explicitly indelete_devicebefore removing the device
Key Design Decisions
vlan_id is nullable
A network with vlan_id = NULL is a plain LAN without 802.1Q tagging. This allows modelling both tagged and untagged networks in the same table. The UI distinguishes them with "LAN" vs "VLAN X" badges.
The vlans table was originally created with vlan_id NOT NULL. The migration _migrate_vlan_nullable() recreates it (SQLite cannot ALTER COLUMN).
Interfaces as a separate table
A device can belong to multiple networks simultaneously. The device_interfaces table is a join table with extra attributes (IP, name, is_upstream). A device appears in every topology card that corresponds to one of its interfaces.
is_gateway and is_livebox
These boolean flags drive the special WAN and Gateway cards in the topology view. They are independent of network membership — a gateway device can also have interfaces in various VLANs.
No foreign key enforcement at the SQLite level
SQLAlchemy's ForeignKey declarations define the schema, but SQLite does not enforce FK constraints unless PRAGMA foreign_keys=ON is set per-connection. The application does not enable this pragma, so referential integrity is maintained by application logic (explicit deletes in the routers).
SQLite Migrations
Migrations are idempotent Python functions that run at startup before Base.metadata.create_all. They check for the presence of columns or tables before acting, so they are safe to run on every container start.
Pattern for adding a nullable column:
def _migrate_my_column():
with engine.connect() as conn:
if not conn.execute(text(
"SELECT name FROM sqlite_master WHERE type='table' AND name='devices'"
)).fetchone():
return
cols = [row[1] for row in conn.execute(text("PRAGMA table_info(devices)")).fetchall()]
if 'my_column' not in cols:
conn.execute(text("ALTER TABLE devices ADD COLUMN my_column VARCHAR"))
conn.commit()
Device Types
18 valid values for devices.type:
| Value | Description |
|---|---|
server |
Physical or virtual server |
switch |
Network switch |
router |
Network router |
nas |
Network-attached storage |
gateway |
Internet gateway / firewall |
livebox |
ISP-provided box (WAN) |
access_point |
Wi-Fi access point |
camera |
IP camera |
temperature |
Temperature sensor |
sensor |
Generic sensor |
hub |
Network hub |
smart_plug |
Smart power plug |
alarm |
Alarm system |
light |
Smart light |
doorbell |
Smart doorbell |
desktop |
Desktop computer |
laptop |
Laptop computer |
other |
Anything else |
url is hidden in the device form for desktop and laptop — these types have no web UI.
Virtualisation Types
devices.virt_type valid values:
| Value | Display | Badge |
|---|---|---|
null |
(not shown) | — |
baremetal |
Bare metal | — |
lxc |
LXC container | blue "LXC" |
qemu |
QEMU/KVM VM | purple "VM" |