Answers the two questions left open on #888 after #893.
INGESTOR_NODE_ID was required for PROTOCOL=reticulum because a passive
announce listener has no handshake revealing "our" node id. The premise
holds; the conclusion did not follow. The ingestor now owns an RNS
identity, generated on first run and stored 0600 as potato_mesh_identity
inside the app-owned RETICULUM_CONFIG_DIR, and derives its !xxxxxxxx
through the same identity-hash mapping applied to every peer, so its own
row is shaped like any other Reticulum row. A plain PROTOCOL=reticulum
deployment brings up the heartbeat, and so the reticulum packets/hour
scope, unaided; the variable still overrides, which also means no key is
generated for a deployment that does not need one. The identity is local
and never announced, so nothing new transmits. Persist-or-nothing is
deliberate: an unstorable identity would be regenerated per start and
each generation is a different node id, filing one orphan ingestor row
per restart, so the provider reports no id and warns instead. An existing
but unreadable key file is never overwritten. The startup warning #890
emitted for an unset INGESTOR_NODE_ID is removed.
CONNECTION and RETICULUM_CONFIG_DIR/RETICULUM_INTERFACES are disjoint
rather than in conflict: CONNECTION names one serial, TCP, or BLE
endpoint and an RNS stack has no such thing, which is why connect() has
always ignored it. What was wrong was the silence, since the image sets a
serial default for every protocol. connect() now says once at info that
the value is dropped and names the two variables that do apply. The image
default stays: removing it would change how meshtastic and meshcore
containers resolve their port, and a Reticulum follow-up is the wrong
change to carry that.
SPEC RN9/RN10, ACCEPTANCE RN-A9/RN-A10; CONTRACTS, README and
.env.example reconciled. 100% line and branch coverage on the provider;
pytest 1442 passed, rspec 1717 examples 0 failures.
* fix reticulum protocol loose ends from #888 review
* data: fix quoted Compose defaults blacking out every channel
* data,web: fix four defects found reviewing this PR
The periodic activity announcement was gated only by RX_ONLY, which
defaults to off, so a stock ingestor deployed to feed a map starts
broadcasting on its community's default channel without the operator
having chosen to. The only opt-out, RX_ONLY=1, also silences the
MeshCore telemetry polls, so "ingest but stay quiet" was not expressible.
Add an ANNOUNCE boolean (default 0) as an opt-in gate on top of RX_ONLY,
which keeps its meaning as the global TX kill switch and overrides
ANNOUNCE=1. Amend SPEC MA7 (which had explicitly ruled out a separate
enable env) and MA-A7 with the reasoning, document both flags in the
README env table — the RX_ONLY row did not mention the announcement at
all — and add gate unit tests for all four combinations plus the
missing-attribute fail-closed path.
Adds an optional passive UDP transport (TRANSPORT=udp) that reads the node's
"Mesh via UDP" LAN multicast instead of holding the radio's single API/serial
slot, filters to the PRIMARY channel by channel-hash (fail-closed), decrypts
with the default PSK, and enriches payloads to match the API-path packet shape
so the collector receives identical records. Implemented as a MeshProtocol
provider; 100% unit coverage on new modules; real-capture fixtures included
(node IDs/GPS anonymized). See PR description for details.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>