mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-13 23:21:19 +10:00
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:
+22
-7
@@ -156,7 +156,9 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
||||
channelSettings.psk.bytes[0] = defaultpskIndex;
|
||||
channelSettings.psk.size = 1;
|
||||
strncpy(channelSettings.name, "", sizeof(channelSettings.name));
|
||||
channelSettings.module_settings.position_precision = 13; // default to sending location on the primary channel
|
||||
// Position sharing is OPT-IN: precision 0 means "do not broadcast location". A user (or the phone app)
|
||||
// must explicitly raise precision to start sharing. See the one-time opt-in migration in NodeDB.cpp.
|
||||
channelSettings.module_settings.position_precision = 0;
|
||||
channelSettings.has_module_settings = true;
|
||||
|
||||
ch.has_settings = true;
|
||||
@@ -436,9 +438,11 @@ bool cryptoKeyIsPublic(const CryptoKey &key)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Channels::usesPublicKey(ChannelIndex chIndex)
|
||||
bool channelFileUsesPublicKey(const meshtastic_ChannelFile &cf, ChannelIndex chIndex)
|
||||
{
|
||||
const meshtastic_Channel &ch = getByIndex(chIndex);
|
||||
if (chIndex >= cf.channels_count)
|
||||
return false;
|
||||
const meshtastic_Channel &ch = cf.channels[chIndex];
|
||||
if (!ch.has_settings || ch.role == meshtastic_Channel_Role_DISABLED)
|
||||
return false;
|
||||
|
||||
@@ -446,10 +450,14 @@ bool Channels::usesPublicKey(ChannelIndex chIndex)
|
||||
if (psk.size == 0) {
|
||||
// Secondary channels inherit the primary key when unset; primary size==0 means encryption disabled.
|
||||
if (ch.role == meshtastic_Channel_Role_SECONDARY) {
|
||||
// Guard against malformed configs with no PRIMARY channel (primaryIndex could point back to us).
|
||||
if (primaryIndex == chIndex)
|
||||
return true; // fail closed: treat as public
|
||||
return usesPublicKey(primaryIndex);
|
||||
// Resolve against the PRIMARY channel's key. The singleton's primaryIndex isn't available in
|
||||
// the raw-struct path (this runs during boot migration before initDefaults), so scan by role.
|
||||
// Fail closed to "public" if no distinct PRIMARY is found (malformed config).
|
||||
for (pb_size_t p = 0; p < cf.channels_count; p++) {
|
||||
if (cf.channels[p].role == meshtastic_Channel_Role_PRIMARY)
|
||||
return (p == chIndex) ? true : channelFileUsesPublicKey(cf, (ChannelIndex)p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -462,6 +470,13 @@ bool Channels::usesPublicKey(ChannelIndex chIndex)
|
||||
return (psk.size == sizeof(defaultpsk) && memcmp(psk.bytes, defaultpsk, sizeof(defaultpsk) - 1) == 0);
|
||||
}
|
||||
|
||||
bool Channels::usesPublicKey(ChannelIndex chIndex)
|
||||
{
|
||||
// Delegates to the pure, on-disk-struct variant so the two can't drift. getByIndex() reads the same
|
||||
// global channelFile, so this is behavior-preserving for the position-precision clamp callers.
|
||||
return channelFileUsesPublicKey(channelFile, chIndex);
|
||||
}
|
||||
|
||||
bool Channels::isWellKnownChannel(ChannelIndex chIndex)
|
||||
{
|
||||
const auto &ch = getByIndex(chIndex);
|
||||
|
||||
Reference in New Issue
Block a user