feat(config): make position & telemetry broadcast opt-in (#10929)

Position sharing was opt-out (the default primary channel shipped
position_precision=13) while device telemetry was already opt-in, and a
normal firmware upgrade preserves saved config, so existing nodes stayed
position-on. This makes both broadcasts opt-in, both on a fresh flash and via
a one-time migration for upgrading nodes.

- Fresh default: initDefaultChannel now sets position_precision=0.
- One-time migration in loadFromDisk, gated on a dedicated
  POSITION_TELEMETRY_OPTIN_VER (26) watermark kept separate from
  DEVICESTATE_CUR_VER (bumping that would re-run the NodeDatabase v24
  legacy decoder on already-migrated v25 DBs): disables position broadcast
  on PUBLIC/default-PSK channels and forces every device-telemetry
  mesh-broadcast flag plus the MQTT map-report location off.
- Private-PSK channels are left untouched: a channel with a custom key is a
  deliberate trusted-group setup, so its configured precision is preserved.
- Idempotent: ordinary saves never re-stamp .version, so a user who
  re-enables sharing is not re-disabled on the next boot.
- Added pure channelFileUsesPublicKey() (operates on the raw ChannelFile,
  since the channels singleton isn't initialized during loadFromDisk) and
  refactored Channels::usesPublicKey() to delegate to it.
- New test/test_optin_migration native suite (14 cases).
This commit is contained in:
Ben Meadors
2026-07-07 14:58:58 -05:00
committed by GitHub
parent d16ae2b098
commit 8d20606203
6 changed files with 305 additions and 8 deletions
+16
View File
@@ -90,6 +90,15 @@ DeviceState versions used to be defined in the .proto file but really only this
// at boot via the parallel deviceonly_legacy descriptor and re-saved as v25.
#define DEVICESTATE_MIN_VER 24
// One-time behavioral migration marker for the 2.8 position/telemetry opt-in flip.
// Deliberately kept separate from DEVICESTATE_CUR_VER: that constant also drives the
// NodeDatabase slim-schema legacy gate (NodeDB.cpp, `nodeDatabase.version < CUR_VER`),
// so bumping it would wrongly re-run the v24 legacy decoder on already-migrated v25
// node DBs. This watermark is stamped only onto channelFile.version / moduleConfig.version
// once the opt-in migration has run. RESERVES 26 - the next real on-disk schema change
// should raise DEVICESTATE_CUR_VER to 27, not 26.
#define POSITION_TELEMETRY_OPTIN_VER 26
extern meshtastic_DeviceState devicestate;
extern meshtastic_NodeDatabase nodeDatabase;
extern meshtastic_ChannelFile channelFile;
@@ -154,6 +163,13 @@ inline bool shouldDropPacketForPreHop(const meshtastic_MeshPacket &p)
/// Rate-limited debug log when hop_start is invalid/missing and packet is dropped.
void logHopStartDrop(const meshtastic_MeshPacket &p, const char *context);
/// 2.8 position/telemetry opt-in migration (pure field mutators; exposed for native tests).
/// Disable position broadcast on every PUBLIC/default-PSK channel (precision -> 0); private-PSK
/// channels (deliberate trusted groups) are left untouched.
void optInDisablePositionSharing(meshtastic_ChannelFile &cf);
/// Force all mesh-broadcast device telemetry (and the MQTT map-report location) back to opt-in/off.
void optInDisableTelemetryBroadcast(meshtastic_LocalModuleConfig &mc);
enum LoadFileResult {
// Successfully opened the file
LOAD_SUCCESS = 1,