Files
stupid-simple-network-inven…/docs/data-model.md
T
olivier 88cf6458d0 Initial commit — Stupid Simple Network Inventory
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>
2026-05-17 09:19:19 +02:00

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

  • Device 1 → N DeviceInterface (cascade delete-orphan)
  • Vlan 1 → N DeviceInterface (nullable FK — deleting a VLAN sets vlan_id to NULL on its interfaces)
  • Link references Device twice (source, target) — links are deleted explicitly in delete_device before 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"