.env.example still described the #896 model: the ingestor owning an RNS
identity and deriving its !xxxxxxxx from "the transport identity already
in RETICULUM_CONFIG_DIR". #897 shipped the opposite. RE8 excludes the
transport identity from the pick, because RNS generates it as an
independent keypair that matches none of the operator's announced
destinations; the id is the discovered primary identity, the one
announcing the most destinations on the machine. README says this
correctly and .env.example contradicted it, pointing operators at the
hash rnstatus prints as "Transport Instance".
The strands-the-old-row caveat #897 added to README and CHANGELOG is
carried over too, since .env.example is where an operator is standing
when they set the variable that moves the id.
Two guards in the deployment-surface class, both negative-tested against
main, where they correctly fail.
pytest 1443 passed; black clean.
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.