dialyzer: fix unknown_type warnings (60 → 0)

- Add @type t :: %__MODULE__{} to schemas referenced by callers:
  ApiToken, Monitoring.Check, OnCall.Schedule, SiteOutage,
  NotificationDigest, Snmp.WirelessClient, Topology.DeviceLink,
  Agent.AgentJob, Agent.MikrotikResult.
- Proto.Types: qualify forward references to nested modules with
  Types. prefix, and fix Metric typo (should be union type metric()).
- data_loaders.ex / chart_builders.ex: Snmp.SNMPDevice.t was a ghost
  spec — module is Snmp.Device.

Warnings: 328 → 242.
This commit is contained in:
Graham McIntire 2026-04-21 09:43:18 -05:00
parent eeacfa4e70
commit 04e7d5ac23
11 changed files with 52 additions and 34 deletions

View file

@ -12,6 +12,8 @@ defmodule Towerops.Alerts.NotificationDigest do
alias Towerops.Accounts.User
alias Towerops.Organizations.Organization
@type t :: %__MODULE__{}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "notification_digests" do

View file

@ -14,6 +14,8 @@ defmodule Towerops.Alerts.SiteOutage do
alias Towerops.Organizations.Organization
alias Towerops.Sites.Site
@type t :: %__MODULE__{}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "site_outages" do

View file

@ -12,6 +12,8 @@ defmodule Towerops.ApiTokens.ApiToken do
import Ecto.Changeset
@type t :: %__MODULE__{}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id

View file

@ -20,6 +20,8 @@ defmodule Towerops.Monitoring.Check do
alias Towerops.Devices.Device
alias Towerops.Organizations.Organization
@type t :: %__MODULE__{}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id

View file

@ -10,6 +10,8 @@ defmodule Towerops.OnCall.Schedule do
alias Towerops.OnCall.Override
alias Towerops.Organizations.Organization
@type t :: %__MODULE__{}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "on_call_schedules" do

View file

@ -532,6 +532,8 @@ end
defmodule Towerops.Agent.AgentJob do
@moduledoc false
@type t :: %__MODULE__{}
defstruct job_id: "",
job_type: :DISCOVER,
device_id: "",
@ -692,6 +694,8 @@ defmodule Towerops.Agent.MikrotikResult do
@moduledoc false
alias Towerops.Agent.MikrotikSentence
@type t :: %__MODULE__{}
defstruct device_id: "", job_id: "", sentences: [], error: "", timestamp: 0
def encode(%__MODULE__{} = r) do

View file

@ -118,8 +118,8 @@ defmodule Towerops.Proto.Types do
@type t :: %__MODULE__{
version: String.t(),
poll_interval_seconds: non_neg_integer(),
devices: [Device.t()],
checks: [Check.t()]
devices: [Types.Device.t()],
checks: [Types.Check.t()]
}
end
@ -152,10 +152,10 @@ defmodule Towerops.Proto.Types do
id: String.t(),
name: String.t(),
ip_address: String.t(),
snmp: SnmpConfig.t() | nil,
snmp: Types.SnmpConfig.t() | nil,
poll_interval_seconds: non_neg_integer(),
sensors: [Sensor.t()],
interfaces: [Interface.t()],
sensors: [Types.Sensor.t()],
interfaces: [Types.Interface.t()],
monitoring_enabled: boolean(),
check_interval_seconds: non_neg_integer()
}
@ -207,15 +207,15 @@ defmodule Towerops.Proto.Types do
@enforce_keys [:metrics]
defstruct [:metrics]
@type t :: %__MODULE__{metrics: [Metric.t()]}
@type t :: %__MODULE__{metrics: [Types.metric()]}
end
@type metric ::
{:sensor_reading, SensorReading.t()}
| {:interface_stat, InterfaceStat.t()}
| {:neighbor_discovery, NeighborDiscovery.t()}
| {:monitoring_check, MonitoringCheck.t()}
| {:check_result, CheckResult.t()}
{:sensor_reading, Types.SensorReading.t()}
| {:interface_stat, Types.InterfaceStat.t()}
| {:neighbor_discovery, Types.NeighborDiscovery.t()}
| {:monitoring_check, Types.MonitoringCheck.t()}
| {:check_result, Types.CheckResult.t()}
defmodule SensorReading do
@moduledoc false
@ -323,10 +323,10 @@ defmodule Towerops.Proto.Types do
end
@type check_config ::
{:http, HttpCheckConfig.t()}
| {:tcp, TcpCheckConfig.t()}
| {:dns, DnsCheckConfig.t()}
| {:ssl, SslCheckConfig.t()}
{:http, Types.HttpCheckConfig.t()}
| {:tcp, Types.TcpCheckConfig.t()}
| {:dns, Types.DnsCheckConfig.t()}
| {:ssl, Types.SslCheckConfig.t()}
| :no_config
defmodule Check do
@ -435,7 +435,7 @@ defmodule Towerops.Proto.Types do
@enforce_keys [:checks]
defstruct [:checks]
@type t :: %__MODULE__{checks: [Check.t()]}
@type t :: %__MODULE__{checks: [Types.Check.t()]}
end
defmodule AgentJobList do
@ -443,7 +443,7 @@ defmodule Towerops.Proto.Types do
@enforce_keys [:jobs]
defstruct [:jobs]
@type t :: %__MODULE__{jobs: [AgentJob.t()]}
@type t :: %__MODULE__{jobs: [Types.AgentJob.t()]}
end
defmodule AgentJob do
@ -471,10 +471,10 @@ defmodule Towerops.Proto.Types do
job_id: String.t(),
job_type: Types.job_type(),
device_id: String.t(),
snmp_device: SnmpDevice.t() | nil,
queries: [SnmpQuery.t()],
mikrotik_device: MikrotikDevice.t() | nil,
mikrotik_commands: [MikrotikCommand.t()]
snmp_device: Types.SnmpDevice.t() | nil,
queries: [Types.SnmpQuery.t()],
mikrotik_device: Types.MikrotikDevice.t() | nil,
mikrotik_commands: [Types.MikrotikCommand.t()]
}
end
@ -608,7 +608,7 @@ defmodule Towerops.Proto.Types do
@type t :: %__MODULE__{
device_id: String.t(),
job_id: String.t(),
sentences: [MikrotikSentence.t()],
sentences: [Types.MikrotikSentence.t()],
error: String.t(),
timestamp: non_neg_integer()
}
@ -631,7 +631,7 @@ defmodule Towerops.Proto.Types do
device_id: String.t(),
job_id: String.t(),
local_system_name: String.t(),
neighbors: [LldpNeighbor.t()],
neighbors: [Types.LldpNeighbor.t()],
timestamp: non_neg_integer()
}
end

View file

@ -9,6 +9,8 @@ defmodule Towerops.Snmp.WirelessClient do
import Ecto.Changeset
@type t :: %__MODULE__{}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "wireless_clients" do

View file

@ -14,6 +14,8 @@ defmodule Towerops.Topology.DeviceLink do
alias Towerops.Snmp.Interface
alias Towerops.Topology.DeviceLinkEvidence
@type t :: %__MODULE__{}
@valid_link_types ~w(lldp cdp mac_match wireless_association arp_inference manual)
@primary_key {:id, :binary_id, autogenerate: true}

View file

@ -109,7 +109,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.ChartBuilders do
Returns JSON-encoded chart data or nil if no matching sensors found.
"""
@spec load_sensor_chart_data(Snmp.SNMPDevice.t() | nil, list(String.t())) ::
@spec load_sensor_chart_data(Snmp.Device.t() | nil, list(String.t())) ::
String.t() | nil
def load_sensor_chart_data(nil, _sensor_types), do: nil
@ -189,7 +189,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.ChartBuilders do
Returns JSON-encoded chart data or nil if no traffic data available.
"""
@spec load_overall_traffic_chart_data(Snmp.SNMPDevice.t() | nil) :: String.t() | nil
@spec load_overall_traffic_chart_data(Snmp.Device.t() | nil) :: String.t() | nil
def load_overall_traffic_chart_data(nil), do: nil
def load_overall_traffic_chart_data(snmp_device) do

View file

@ -74,7 +74,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.DataLoaders do
Enriches sensors and interfaces with their latest readings/stats.
"""
@spec load_snmp_data(binary()) :: %{
device: Snmp.SNMPDevice.t() | nil,
device: Snmp.Device.t() | nil,
interfaces: list(),
sensors: list()
}
@ -115,28 +115,28 @@ defmodule ToweropsWeb.DeviceLive.Helpers.DataLoaders do
@doc """
Loads VLAN information for an SNMP device.
"""
@spec load_vlans(Snmp.SNMPDevice.t() | nil) :: list()
@spec load_vlans(Snmp.Device.t() | nil) :: list()
def load_vlans(nil), do: []
def load_vlans(snmp_device), do: Snmp.list_vlans(snmp_device.id)
@doc """
Loads IP addresses for an SNMP device.
"""
@spec load_ip_addresses(Snmp.SNMPDevice.t() | nil) :: list()
@spec load_ip_addresses(Snmp.Device.t() | nil) :: list()
def load_ip_addresses(nil), do: []
def load_ip_addresses(snmp_device), do: Snmp.list_ip_addresses(snmp_device.id)
@doc """
Loads processor information for an SNMP device.
"""
@spec load_processors(Snmp.SNMPDevice.t() | nil) :: list()
@spec load_processors(Snmp.Device.t() | nil) :: list()
def load_processors(nil), do: []
def load_processors(snmp_device), do: Snmp.list_processors(snmp_device.id)
@doc """
Loads storage information for an SNMP device.
"""
@spec load_storage(Snmp.SNMPDevice.t() | nil) :: list()
@spec load_storage(Snmp.Device.t() | nil) :: list()
def load_storage(nil), do: []
def load_storage(snmp_device), do: Snmp.list_storage(snmp_device.id)
@ -162,7 +162,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.DataLoaders do
Returns firmware release information if available, nil otherwise.
Currently only supports MikroTik RouterOS.
"""
@spec get_available_firmware(Snmp.SNMPDevice.t() | nil) :: map() | nil
@spec get_available_firmware(Snmp.Device.t() | nil) :: map() | nil
def get_available_firmware(nil), do: nil
def get_available_firmware(snmp_device) do
@ -394,7 +394,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.DataLoaders do
@doc """
Loads transceiver data for a device.
"""
@spec load_transceivers(Snmp.SNMPDevice.t() | nil) :: map()
@spec load_transceivers(Snmp.Device.t() | nil) :: map()
def load_transceivers(nil) do
%{
transceivers: [],
@ -414,7 +414,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.DataLoaders do
@doc """
Loads printer supplies data for a device.
"""
@spec load_printer_supplies(Snmp.SNMPDevice.t() | nil) :: map()
@spec load_printer_supplies(Snmp.Device.t() | nil) :: map()
def load_printer_supplies(nil) do
%{
printer_supplies: [],
@ -434,7 +434,7 @@ defmodule ToweropsWeb.DeviceLive.Helpers.DataLoaders do
@doc """
Loads hardware inventory (entity physical) data for a device.
"""
@spec load_hardware_inventory(Snmp.SNMPDevice.t() | nil) :: map()
@spec load_hardware_inventory(Snmp.Device.t() | nil) :: map()
def load_hardware_inventory(nil) do
%{
hardware_inventory: [],