Device identity and naming
A device in Nyxtrace is not a MAC address and not an IP address. It is an identity cluster: a set of weighted anchors observed over time, with the evidence for each one kept.
That sounds abstract until you try the alternatives. Identify by IP and a DHCP lease change becomes a new device. Identify by MAC and every modern phone becomes a new device every few days. Either way the inventory fills with ghosts and every device is permanently inside its learning phase.
Anchors
Section titled “Anchors”An anchor is one observation that says something about who a device is.
| Class | From | Role |
|---|---|---|
mac |
DHCP, controller, layer 2 | Establishes |
mac_random |
A MAC with the locally administered bit set | Confirms only |
mac_oui |
The vendor prefix of an administered MAC | Confirms only |
dhcp_hostname |
The host name in a DHCP request | Establishes |
dhcp_fingerprint |
The DHCP parameter and class fingerprint | Confirms only |
mdns |
A .local name |
Establishes |
authoritative_map |
A name a person assigned in a controller | Establishes |
dot1x |
A RADIUS identity | Establishes |
duid, agent |
A DHCPv6 identifier, an endpoint agent | Establishes |
ja4 |
A TLS client fingerprint | Confirms only |
behavior |
Behavioural similarity | Confirms only |
recurrence |
The same anchors agreeing again on a separate day | Confirms only |
The split in that last column is the important one. A confirming class can raise confidence but can never establish an identity on its own. Vendor prefix, DHCP fingerprint and TLS fingerprint are shared by thousands of identical devices; treating one as an identity would merge every phone of the same model into one.
Where a name comes from
Section titled “Where a name comes from”An address is a location, not a name. An hourly job resolves the name to show
from every source that knows one, in a fixed priority, and the interface says
which source it came from (name_source):
| Priority | Source | name_source |
Confidence | Where it comes from |
|---|---|---|---|---|
| 1 | Operator | manual |
1.00 | A rename in the interface — PATCH /api/v1/devices/{id} |
| 2 | Authoritative inventory | authoritative_map |
0.90 | The client name of a UniFi controller |
| 3 | DHCP host name | dhcp |
0.75 | DHCP option 12, from the retained IDS events |
| 4 | mDNS name | mdns |
0.70 | A .local name from the DNS events |
| 5 | Reverse DNS | reverse_dns |
0.55 | A PTR record from the appliance’s own resolver |
| 6 | Address | address |
0.00 | Nothing knew a name |
The order deliberately puts the DHCP host name above the mDNS name, unlike the anchor weights above: identity asks which name survives a MAC rotation, naming asks which name an operator recognises, and the name a device asks to be called by is the one that was configured on the device itself.
Every name goes through one normalisation, so a manual name and a DHCP host name
cannot differ in what they are allowed to be: a host-name source yields a DNS
label (lower case, no spaces, .local removed, so the same name from two
sources is one name), while an operator-assigned name keeps its case and its
spaces, because “Jannik’s iPhone” is exactly the shape those sources produce. An
address, a generic placeholder (localhost, unknown, android, …) and
anything over 200 characters are never a name.
A device still named after its address gets upgraded the moment a proven host name appears. A name a human confirmed is never downgraded — it is an overlay that no later resolution overwrites, and renaming a device says nothing about what kind of device it is.
A DHCP host name expires with its lease. The job takes the last host name an address was announced with and the announced lease time as its validity, or 48 hours — two renewal cycles — when none was logged. A name from a finished lease stops being shown and stays listed as a former name, instead of quietly describing whoever holds that address now.
The reverse-DNS source is bounded
Section titled “The reverse-DNS source is bounded”It is the only naming source that talks to the network, so it is limited in
every direction: only addresses inside the tenant’s own VLAN ranges are asked
about at all, a device a higher-priority source already named is not asked
about, the timeout is 300 ms against the appliance’s own resolver over loopback,
a token bucket allows 20 queries per second with a burst of 40 and at most 2,000
addresses per run, and answers are cached for an hour (absences for 15 minutes).
A query the rate limit stopped is not cached as “no name”: a query that was
never sent proves nothing. NXDOMAIN, an empty answer, a name that is itself an
address and a generic name all mean the same thing — no name. The first label of
the answer becomes the name (camera-01 from camera-01.home.example).
The job runs hourly, is read-only against everything that already exists, and
writes only its own name overlay. It is on by default and
NDR_NAMING_ENABLED=false switches it off.
Facts are not anchors
Section titled “Facts are not anchors”A controller also reports which access point a client is on, which SSID, which switch port, which VLAN, the signal strength and whether it is wired. Those are facts about the device, recorded with their source and their age — not claims about its identity.
Keeping that line clean is what stops “two devices were on the same access point” from becoming “two devices are the same device”.
Conflicting sources
Section titled “Conflicting sources”Every fact carries its source and its recency, and a contradiction is shown as a contradiction rather than resolved silently by whichever source wrote last. If DHCP says one host name and the controller says another, you see both, with who said what and when.
An unavailable source leaves its facts stale, never deleted. A controller outage does not erase what it told you yesterday, and no identity decision is made on stale data alone.
What the interface shows
Section titled “What the interface shows”The device detail lists every anchor with its class,
value, source, weight, first and last seen, the number of separate days it was
observed, and two markers: randomized for a privacy address, and confirming
for a class that cannot establish identity. Below that: every merge event with
its rule, confidence and anchors, and any split that reverted one.
A confidence below 0.90 means the identity is derived, and the interface says so instead of presenting it as fact.