@@ -23,11 +23,11 @@ to be kept honest against each decoder's actual output.
2323## The adapter shape
2424
2525Each decoder is represented by an adapter that knows how to do a few things:
26- recognize its own decoder from the receiver file , describe which pieces of
27- operational data that decoder actually provides, and translate each of the four
28- files into Ident types. An adapter that cannot supply a given file says so
29- rather than guessing; the UAT decoder, for instance, emits no statistics file
30- and no range outline, and its adapter reports both as absent.
26+ recognize its own decoder from the files that have arrived , describe which
27+ pieces of operational data that decoder actually provides, and translate each
28+ of the four files into Ident types. An adapter that cannot supply a given file
29+ says so rather than guessing; the UAT decoder, for instance, emits no
30+ statistics file and no range outline, and its adapter reports both as absent.
3131
3232The receiver file translates into a small record holding the decoder name, a
3333version string, and the receiver's coordinates when present. The statistics
@@ -38,40 +38,48 @@ file becomes a polygon.
3838
3939## How a decoder is identified
4040
41- Identification runs when the receiver file changes, not on every aircraft frame.
42- Aircraft data arrives at roughly one update per second; re-deciding the decoder
43- identity that often would be wasted work, and the identity rarely changes once a
44- deployment is running. The decision is made from the content of the receiver
45- file rather than from file paths, because an operator can mount a decoder's
46- output wherever they like.
47-
48- There is no scoring. Adapters are tried in a fixed order and the first one that
49- recognizes the receiver file wins; nothing weighs how well several adapters
50- match. readsb is tried first and is identified by an explicit flag it sets in
51- its receiver file. The UAT decoder is tried next and is identified by a version
52- string that begins with its name. dump1090-fa is tried last and is identified by
53- its version string containing a known marker. A version string that is merely
54- present, or non-empty, does not identify dump1090-fa; the marker has to be there.
41+ Identification is content-based, not path-based. Operators can mount a decoder's
42+ output wherever they like, and some stacks write receiver metadata that is too
43+ generic to identify the stack by itself. ` identd ` therefore considers the
44+ receiver, aircraft, statistics, and outline files together as evidence for the
45+ adapter selection.
46+
47+ Receiver metadata still carries the strongest signals when it includes an
48+ explicit decoder marker. When it does not, the shape of the statistics and
49+ aircraft files can still be enough to identify a supported decoder. This is
50+ deliberately a "what can this adapter safely normalize?" decision rather than a
51+ "what product name is this directory?" decision. The result is one of four
52+ states:
53+
54+ - An operator override names a supported decoder, so that adapter is selected.
55+ - Exactly one adapter has enough evidence, so that adapter is selected.
56+ - No adapter has enough evidence, so the producer remains unknown.
57+ - More than one adapter has equally strong evidence, so ` identd ` reports an
58+ ambiguous producer. If no adapter has been selected yet, producer data waits
59+ until more evidence arrives or an override is set. If the currently selected
60+ adapter is still one of the tied candidates, ` identd ` keeps that adapter for
61+ normalization and treats the tie as a diagnostic rather than a reason to
62+ demote the stream.
5563
5664``` mermaid
5765flowchart TD
58- C[receiver file changes] --> R{readsb flag set?}
59- R -->|yes| RB[readsb]
60- R -->|no| U{version begins with the UAT decoder name?}
61- U -->|yes| UAT[dump978 / skyaware978]
62- U -->|no| D{version contains the dump1090-fa marker?}
63- D -->|yes| DF[dump1090-fa]
64- D -->|no| UN[unclassified]
66+ F[receiver, aircraft, stats, or outline file changes] --> E[update observed evidence]
67+ E --> O{operator override set?}
68+ O -->|yes| S[select named supported adapter]
69+ O -->|no| A[adapters evaluate evidence]
70+ A --> R{classification result}
71+ R -->|one supported adapter| S
72+ R -->|not enough evidence| N[unknown]
73+ R -->|several adapters tie| M[ambiguous]
6574```
6675
67- Order is the only tie-breaker, and that has a consequence worth stating: a feed
68- whose version string begins with the UAT decoder's name is claimed by that
69- adapter before the dump1090-fa check ever runs. Keeping order as the sole
70- priority mechanism avoids a configuration table that most deployments would
71- never touch, but it does mean the order itself is load-bearing, including in
72- tests, where reordering the adapters changes which one claims an ambiguous fixture.
76+ Unknown and ambiguous states are surfaced as diagnostics, including the
77+ strongest evidence ` identd ` has seen so far. That keeps an unsupported or
78+ unusual stack visible to the operator without guessing a decoder. Once a decoder
79+ has already been selected, later ambiguous evidence only blocks a switch away
80+ from that decoder unless the operator overrides it or stronger evidence appears.
7381
74- A decoder that no adapter recognizes stays unclassified . Some decoders write
82+ A decoder that no adapter recognizes stays unknown . Some decoders write
7583aircraft JSON that Ident could in principle read but are simply not recognized
7684by any adapter and so never get classified. Others are structurally
7785incompatible: a decoder whose aircraft file is a bare array, without the
@@ -85,20 +93,26 @@ published.
8593An operator can override automatic identification and name the decoder
8694explicitly through an environment variable or its matching command-line flag,
8795with a few accepted spellings per decoder. The override selects the adapter, but
88- automatic identification still runs on every receiver-file change. When the two
89- disagree, ` identd ` emits a diagnostic rather than quietly trusting the override,
90- so a misconfiguration is visible instead of hidden. If the named decoder is one
91- this build does not support, that is reported too.
92-
93- ## Nothing is published before classification
94-
95- ` identd ` starts the receiver-file watcher right away but holds off on the
96- aircraft, statistics, and outline watchers until a decoder has been identified.
97- Until then there is no adapter to translate those files, and starting their
98- watchers early would produce a steady stream of "waiting for classification"
99- diagnostics, one per file update. The HTTP server starts before this gate so the
100- interface stays reachable while the wait plays out. No decoder-shaped data
101- reaches the hub until classification succeeds.
96+ automatic identification still evaluates the observed files. When the observed
97+ evidence points at a different decoder, ` identd ` emits a diagnostic rather than
98+ quietly trusting the override, so a misconfiguration is visible instead of
99+ hidden. If the named decoder is one this build does not support, that is
100+ reported too.
101+
102+ ## Nothing is published before selection
103+
104+ ` identd ` starts all producer-file watchers during startup so each file can add
105+ evidence as soon as it appears. When no adapter has been selected yet, unknown
106+ or ambiguous producer files are parsed only far enough to help identify a
107+ supported adapter. They are not published as normalized aircraft, status, or
108+ range data until one adapter can safely handle them.
109+
110+ That distinction matters for compatibility. An unknown decoder may write
111+ aircraft JSON that looks close to a supported shape, but publishing it before an
112+ adapter is selected would let raw decoder semantics leak into Ident's wire
113+ contract. The HTTP server still starts immediately, so the interface stays
114+ reachable while classification is waiting for enough evidence, and the
115+ diagnostic bell explains why live producer data is not flowing yet.
102116
103117## Where the decoders actually differ
104118
@@ -155,11 +169,11 @@ This single on-ground value is what trail segmentation reads (see
155169
156170Alongside the status and aircraft data, ` identd ` publishes a description of which
157171features a decoder supports. Each feature is marked as provided by the decoder,
158- derived by Ident, or unavailable. The adapter sets a conservative baseline for
159- its decoder when the receiver file is read , and live data can promote a feature
160- as statistics or aircraft frames confirm it is actually present. Promotion is
161- one-directional within a single decoder: a later receiver- file update does not
162- demote a feature that earlier live data already established, so the interface
163- does not flicker a capability off and on as files arrive in different orders.
164- A demotion happens only on a real change of circumstance, such as the decoder
165- itself changing.
172+ derived by Ident, or unavailable. The selected adapter sets a conservative
173+ baseline from the evidence it has seen , and live data can promote a feature as
174+ statistics, aircraft frames, or outline files confirm it is actually present.
175+ Promotion is one-directional within a single selected decoder: a later file
176+ update does not demote a feature that earlier live data already established, so
177+ the interface does not flicker a capability off and on as files arrive in
178+ different orders. A demotion happens only on a real change of circumstance, such
179+ as the decoder itself changing or the producer becoming ambiguous again .
0 commit comments