Problem
The ingestor accepts mobile client RX coverage (meshcore/client/{PUBLIC_KEY}/packets, gated by clientRxCoverage.enabled) from every configured MQTT source. Trust in that topic rests on the broker binding the topic pubkey to the publisher's identity (see docs/client-rx-coverage.md, "Trust").
An instance can have several sources: a device-auth broker that binds the topic to a signed per-device token, and a legacy username/password broker where many accounts may write meshcore/#. On such a deployment, any account on the legacy broker could publish coverage under any companion pubkey once the feature is enabled.
Proposal
Add an optional allowlist of sources for the client namespace:
"clientRxCoverage": { "enabled": true, "sources": ["<source name>"] }
- If
sources is set and non-empty, the ingestor handles meshcore/client/... only when the message arrived on a listed mqttSources[].name. Messages from other sources are dropped, with a throttled, bounded log line. They still never fall through to the observer path.
- If
sources is absent or empty, behaviour is unchanged: all sources are accepted, as today. This keeps upstream-compatible defaults.
- An unknown name in
sources (one that matches no configured source) is logged once at startup.
Acceptance
Problem
The ingestor accepts mobile client RX coverage (
meshcore/client/{PUBLIC_KEY}/packets, gated byclientRxCoverage.enabled) from every configured MQTT source. Trust in that topic rests on the broker binding the topic pubkey to the publisher's identity (seedocs/client-rx-coverage.md, "Trust").An instance can have several sources: a device-auth broker that binds the topic to a signed per-device token, and a legacy username/password broker where many accounts may write
meshcore/#. On such a deployment, any account on the legacy broker could publish coverage under any companion pubkey once the feature is enabled.Proposal
Add an optional allowlist of sources for the client namespace:
sourcesis set and non-empty, the ingestor handlesmeshcore/client/...only when the message arrived on a listedmqttSources[].name. Messages from other sources are dropped, with a throttled, bounded log line. They still never fall through to the observer path.sourcesis absent or empty, behaviour is unchanged: all sources are accepted, as today. This keeps upstream-compatible defaults.sources(one that matches no configured source) is logged once at startup.Acceptance
client_receptionsorclient_observers, and creates no observer row.sourcesabsent or empty, behaviour is unchanged (existing tests stay green).docs/client-rx-coverage.mdand the configuration docs describe the option, and why it matters on mixed-broker deployments.handleMessagepath with the source tag, and a mutant (source check removed) fails.cmd/serveris untouched, or read-only if touched; no newmap[string]interface{}.