Files
meshcore-analyzer/cmd
efiten fd825a779c fix(ingestor): name a region scope deterministically, or not at all (#1988)
`matchScope` returns the first configured region whose derived code
equals the packet's `code1` and stops there. Go randomises map iteration
order per `range`, so when two configured regions collide on a payload,
the stored region name depends on which key the runtime happened to
visit first. **The same packet can be named differently on two runs of
the same binary**, and neither answer is evidence of anything.

## How often this actually happens

`code1` is two bytes, so any two configured regions collide on a given
payload with probability 1/65536. That is a curiosity at 5 configured
regions and routine at 150.

Measured on a live instance carrying 159 configured regions, over 41.7
hours and 147,535 transport-scoped packets: **374 collisions, 0.253% of
decisions.** They concentrate on four key pairs rather than scattering,
because `code1` is an HMAC over the payload: a payload that collides
collides every time it is seen, and a flooded packet is seen by many
observers.

The existing comment sizes the function for "≤ 50 regions". A live BE/NL
instance declares 126 distinct region names across its repeaters, so
operators are already past that.

## The rule

`matchingRegions` returns every match; `matchScope` applies one rule:

- exactly one match names the packet
- several matches name nothing

The candidates are equally sourced, there is no principled winner
between them, and storing a wrong region name is worse than storing
none. `""` is already the ingestor's "transport-scoped but unnameable"
state (`scopeNameForDB`), so an ambiguous packet lands in a state the
rest of the system already understands rather than in a new one. Nothing
downstream needs to learn a new value.

The collision is logged, because it is otherwise invisible: such a
packet is stored exactly like one whose region this instance holds no
key for. An operator watching an unnameable count grow deserves to see
which of their own configured regions are colliding, since the fix is
theirs to make.

## Rule 0

Cost is unchanged: the same single pass over the same keys, it just no
longer stops early. The early exit was worth nothing on the common path,
where zero or one key matches and the loop runs to the end either way.
Worst case is unchanged at one HMAC per key per transport-scoped packet.

There is no indexable shortcut to reach for. `code1` is an HMAC over the
packet payload, so nothing is payload-independent to index on, and the
old comment suggesting a "pre-indexed lookup table" is removed rather
than left as a false lead for the next reader.

## Tests

Three, and the fixture matters:

- an unambiguous packet still gets its region name
- a genuinely colliding payload stores the unmatched state instead of a
coin flip
- the ambiguous case run 50 times, because a first-match matcher passes
a single iteration roughly half the time

The collision is **found by searching payloads** (~65k tries, fractions
of a second) rather than asserting on a hand-picked `code1`. The case
only exists when the matcher genuinely finds two names for one packet,
and a fabricated code would only prove the test agrees with itself.

`cd cmd/ingestor && go test ./...` passes apart from
`TestWriteStatsAtomic_SymlinkAtDestIsReplaced`, which needs
`SeCreateSymbolicLinkPrivilege` and fails on Windows on master too. `go
vet` and `gofmt -l` clean.
2026-09-09 17:18:54 +02:00
..