"""Pydantic model for packet rows returned by the backend.""" from datetime import datetime from typing import Optional, Union from pydantic import BaseModel, Field, IPvAnyAddress class PacketDBModel(BaseModel): """Normalized packet representation used across DB and API layers.""" id: Union[int, str] timestamp: datetime = Field(..., description="Packet timestamp in ISO format.") iface: str src_mac: Optional[str] = None dst_mac: Optional[str] = None eth_type: Optional[Union[int, str]] = None ip_proto: Optional[Union[int, str]] = None src_ip: Optional[IPvAnyAddress] = None dst_ip: Optional[IPvAnyAddress] = None src_port: Optional[int] = None dst_port: Optional[int] = None vlan_id: Optional[int] = None length: Optional[int] = None raw_b64: Optional[str] = Field(None, description="Base64-encoded packet bytes.") app_protocol: Optional[str] = Field(None, description="Detected application protocol.") app_master_protocol: Optional[str] = Field(None, description="Detected application master protocol.") app_category: Optional[str] = Field(None, description="nDPI category, if available.") app_confidence: Optional[str] = Field(None, description="nDPI confidence level, if available.") app_hostname: Optional[str] = Field(None, description="Detected hostname/SNI, if available.") app_is_encrypted: Optional[bool] = Field(None, description="Whether detected protocol appears encrypted.") app_risk_score: Optional[int] = Field(None, description="Count/score of detected nDPI risks.") dpi_metadata: Optional[dict] = Field(None, description="Raw DPI metadata from nDPI.") direction: Optional[str] = None packets: Optional[int] = None class Config: schema_extra = { "example": { "id": 123, "timestamp": "2026-03-05T12:34:56.789Z", "iface": "eth0", "src_mac": "aa:bb:cc:dd:ee:ff", "dst_mac": "11:22:33:44:55:66", "eth_type": "IPv4", "ip_proto": "TCP", "src_ip": "192.168.1.10", "dst_ip": "192.168.1.1", "src_port": 54321, "dst_port": 80, "vlan_id": None, "length": 128, "raw_b64": "BASE64...", "app_protocol": "HTTP", "app_master_protocol": "HTTP", "app_category": "Web", "app_confidence": "high", "app_hostname": "example.org", "app_is_encrypted": False, "app_risk_score": 0, "dpi_metadata": {"method": "GET"}, } }