forge: add patch 8 — drop [MCBOT] advert suffix

The auto-discovery of known bots via the suffix only fed DM suppression,
which is moot since DMs are encrypted to one recipient. Channel
coordination now lands via patch 7's request token mechanism, which
doesn't need the suffix. Removes the marker, writeBotAdvertName,
isBotAdvertName, autoLearnKnownBotAdvert, and getAdvertNodeName; reverts
all four advert sites to use _prefs.node_name directly. Removes the
test_bot_advert_marker host test. Manual 'bot known add' from CLI still
works for explicit DM suppression.
This commit is contained in:
cj-vana
2026-05-16 19:55:44 -06:00
parent c13e5474dd
commit 064904e596
10 changed files with 235 additions and 25 deletions

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Fri, 15 May 2026 11:44:21 -0600
Subject: [PATCH 1/7] Add companion radio firmware bot command parity
Subject: [PATCH 1/8] Add companion radio firmware bot command parity
---
.../companion_radio/BotCommandRegistry.cpp | 121 ++

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Fri, 15 May 2026 19:58:42 -0600
Subject: [PATCH 2/7] Harden firmware bot response coordination
Subject: [PATCH 2/8] Harden firmware bot response coordination
---
examples/companion_radio/BotCommands.cpp | 2 +-

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Fri, 15 May 2026 20:09:58 -0600
Subject: [PATCH 3/7] Allow prefixless firmware bot DMs
Subject: [PATCH 3/8] Allow prefixless firmware bot DMs
---
examples/companion_radio/BotPolicy.cpp | 2 +-

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 04:12:02 +0000
Subject: [PATCH 4/7] Align firmware bot commands with upstream behavior
Subject: [PATCH 4/8] Align firmware bot commands with upstream behavior
---
.../companion_radio/BotCommandRegistry.cpp | 25 +-

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 12:38:13 -0600
Subject: [PATCH 5/7] Add hop-aware bot coordination, utility commands, and
Subject: [PATCH 5/8] Add hop-aware bot coordination, utility commands, and
bounded delays
Adds new utility commands (TIME, LORA, ID, NEIGHBORS), neighbor tracking,

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 18:58:28 -0600
Subject: [PATCH 6/7] Mark bot adverts, speed up initial advert, default
Subject: [PATCH 6/8] Mark bot adverts, speed up initial advert, default
contacts auto-overwrite
Three coordination/discoverability fixes:

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 19:33:04 -0600
Subject: [PATCH 7/7] Prefix bot responses with request token for inter-bot
Subject: [PATCH 7/8] Prefix bot responses with request token for inter-bot
suppression
Adds a 4-hex request token (low 16 bits of the request fingerprint) as a

View File

@@ -0,0 +1,227 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 19:55:36 -0600
Subject: [PATCH 8/8] Drop [MCBOT] advert suffix and auto-learn known-bot path
Removes BOT_ADVERT_MARKER / writeBotAdvertName / isBotAdvertName from
FirmwareBot, autoLearnKnownBotAdvert and getAdvertNodeName from MyMesh,
and reverts all four advert call sites (sendBotSelfAdvert,
CMD_SEND_SELF_ADVERT, CMD_EXPORT_CONTACT, MyMesh::advert) to use
_prefs.node_name directly.
The suffix existed so peers could auto-add bots to the known-bot
registry, which gated DM-only suppression in observeKnownBotResponse.
Channel coordination now lands via the request-token mechanism added
in patch 7, which doesn't depend on knowing-who-is-a-bot. DM
collisions don't really happen (DMs are encrypted to one recipient),
so the registry's auto-population was carrying its own weight only
for visual identification of bots in contact lists -- not worth the
naming pollution.
The known-bot registry itself stays (still settable via `bot known
add` from CLI rescue) for anyone who wants explicit DM suppression.
---
examples/companion_radio/BotTypes.h | 2 -
examples/companion_radio/FirmwareBot.cpp | 26 ------------
examples/companion_radio/FirmwareBot.h | 2 -
examples/companion_radio/MyMesh.cpp | 51 ++++--------------------
examples/companion_radio/MyMesh.h | 4 --
5 files changed, 8 insertions(+), 77 deletions(-)
diff --git a/examples/companion_radio/BotTypes.h b/examples/companion_radio/BotTypes.h
index d30fb7f2..ad249300 100644
--- a/examples/companion_radio/BotTypes.h
+++ b/examples/companion_radio/BotTypes.h
@@ -21,8 +21,6 @@
#define BOT_TRACE_TIMEOUT_MILLIS 30000UL
#define BOT_PENDING_TRACE_SLOTS 2
#define BOT_EMERGENCY_PREFIX "EMERGENCY MESSAGE FROM "
-#define BOT_ADVERT_MARKER " [MCBOT]"
-#define BOT_ADVERT_MARKER_LEN 8
#define BOT_EMERGENCY_MAX_PARTS 3
#define BOT_PENDING_EMERGENCY_SLOTS BOT_EMERGENCY_MAX_PARTS
#define BOT_COORDINATOR_PENDING_SLOTS 8
diff --git a/examples/companion_radio/FirmwareBot.cpp b/examples/companion_radio/FirmwareBot.cpp
index 24c79e81..3c310173 100644
--- a/examples/companion_radio/FirmwareBot.cpp
+++ b/examples/companion_radio/FirmwareBot.cpp
@@ -363,32 +363,6 @@ BotWriteResult writeAckResponse(const BotMessage& message, const BotCommand& com
return truncated ? BOT_WRITE_TRUNCATED : BOT_WRITE_OK;
}
-BotWriteResult writeBotAdvertName(const char* node_name, char* output, size_t output_len, size_t* written) {
- if (written) *written = 0;
- if (!output || output_len == 0) return BOT_WRITE_NO_SPACE;
- if (output_len <= BOT_ADVERT_MARKER_LEN) {
- output[0] = 0;
- return BOT_WRITE_NO_SPACE;
- }
-
- size_t base_len = boundedStrLen(node_name, output_len - 1);
- bool truncated = false;
- if (base_len + BOT_ADVERT_MARKER_LEN + 1 > output_len) {
- base_len = output_len - BOT_ADVERT_MARKER_LEN - 1;
- truncated = true;
- }
- if (base_len > 0) memcpy(output, node_name, base_len);
- memcpy(&output[base_len], BOT_ADVERT_MARKER, BOT_ADVERT_MARKER_LEN);
- output[base_len + BOT_ADVERT_MARKER_LEN] = 0;
- if (written) *written = base_len + BOT_ADVERT_MARKER_LEN;
- return truncated ? BOT_WRITE_TRUNCATED : BOT_WRITE_OK;
-}
-
-bool isBotAdvertName(const char* name, size_t name_len) {
- if (!name || name_len < BOT_ADVERT_MARKER_LEN) return false;
- return memcmp(&name[name_len - BOT_ADVERT_MARKER_LEN], BOT_ADVERT_MARKER, BOT_ADVERT_MARKER_LEN) == 0;
-}
-
BotFingerprint fingerprintFor(const BotMessage& message) {
uint64_t hash = 1469598103934665603ULL;
hash = fnv1aUpdateChannel(hash, message);
diff --git a/examples/companion_radio/FirmwareBot.h b/examples/companion_radio/FirmwareBot.h
index 6e5cfd9a..708432a2 100644
--- a/examples/companion_radio/FirmwareBot.h
+++ b/examples/companion_radio/FirmwareBot.h
@@ -16,8 +16,6 @@ BotWriteResult writeResponseForChannel(BotChannelKind channel_kind, bool allow_p
size_t text_len, char* output, size_t output_len, size_t* written);
BotWriteResult writeAckResponse(const BotMessage& message, const BotCommand& command, char* output, size_t output_len,
size_t* written);
-BotWriteResult writeBotAdvertName(const char* node_name, char* output, size_t output_len, size_t* written);
-bool isBotAdvertName(const char* name, size_t name_len);
BotFingerprint fingerprintFor(const BotMessage& message);
BotFingerprint responseFingerprintFor(const BotMessage& message, const char* response_text, size_t response_text_len);
uint16_t requestToken(BotFingerprint request_fingerprint);
diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp
index 02339124..9121d42c 100644
--- a/examples/companion_radio/MyMesh.cpp
+++ b/examples/companion_radio/MyMesh.cpp
@@ -637,7 +637,6 @@ void MyMesh::onContactsFull() {
void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path_len, const uint8_t* path) {
#if CMESH_BOT_ENABLED
- autoLearnKnownBotAdvert(contact);
if ((path_len & 63) == 0) {
float rssi = radio_driver.getLastRSSI();
if (rssi > 32767.0f) rssi = 32767.0f;
@@ -1167,21 +1166,6 @@ void MyMesh::buildBotCommandContext(BotCommandContext &context, BotCommandId com
}
}
-bool MyMesh::autoLearnKnownBotAdvert(const ContactInfo &contact) {
- if (!bot_prefs.enabled || contact.type != ADV_TYPE_CHAT ||
- !FirmwareBot::isBotAdvertName(contact.name, botBoundedStrLen(contact.name, sizeof(contact.name)))) {
- return false;
- }
-
- uint8_t key[BOT_SENDER_KEY_PREFIX_LEN];
- memcpy(key, contact.id.pub_key, sizeof(key));
- if (BotPrefsCodec::findKnownBot(bot_prefs, key)) return false;
- if (!BotPrefsCodec::addKnownBot(bot_prefs, key, BOT_KNOWN_BOT_FLAG_SUPPRESS_NORMAL, "autobot")) return false;
- KnownBotRegistry::add(known_bot_entries, BOT_KNOWN_BOT_SLOTS, key, BOT_KNOWN_BOT_FLAG_SUPPRESS_NORMAL, "autobot");
- saveBotPrefs();
- return true;
-}
-
bool MyMesh::enqueueBotResponse(const BotMessage &message, const ContactInfo *direct_recipient, uint8_t channel_idx,
const char *text, size_t text_len, BotFingerprint request_fingerprint,
BotFingerprint response_fingerprint) {
@@ -2019,12 +2003,10 @@ void MyMesh::sendQueuedEmergencyForwards() {
bool MyMesh::sendBotSelfAdvert(bool flood) {
mesh::Packet* pkt;
- char bot_advert_name[sizeof(((ContactInfo*)0)->name)];
- const char* adv_name = getAdvertNodeName(bot_advert_name, sizeof(bot_advert_name));
if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
- pkt = createSelfAdvert(adv_name);
+ pkt = createSelfAdvert(_prefs.node_name);
} else {
- pkt = createSelfAdvert(adv_name, sensors.node_lat, sensors.node_lon);
+ pkt = createSelfAdvert(_prefs.node_name, sensors.node_lat, sensors.node_lon);
}
if (!pkt) return false;
@@ -2065,17 +2047,6 @@ void MyMesh::tickBot() {
}
#endif
-const char* MyMesh::getAdvertNodeName(char* buf, size_t buf_len) {
-#if CMESH_BOT_ENABLED
- if (bot_prefs.enabled && buf && buf_len > 0) {
- FirmwareBot::writeBotAdvertName(_prefs.node_name, buf, buf_len, NULL);
- return buf;
- }
-#endif
- (void)buf;
- (void)buf_len;
- return _prefs.node_name;
-}
void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packet *pkt, uint32_t timestamp,
const char *text) {
@@ -2819,12 +2790,10 @@ void MyMesh::handleCmdFrame(size_t len) {
}
} else if (cmd_frame[0] == CMD_SEND_SELF_ADVERT) {
mesh::Packet* pkt;
- char adv_buf[sizeof(((ContactInfo*)0)->name)];
- const char* adv_name = getAdvertNodeName(adv_buf, sizeof(adv_buf));
if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
- pkt = createSelfAdvert(adv_name);
+ pkt = createSelfAdvert(_prefs.node_name);
} else {
- pkt = createSelfAdvert(adv_name, sensors.node_lat, sensors.node_lon);
+ pkt = createSelfAdvert(_prefs.node_name, sensors.node_lat, sensors.node_lon);
}
if (pkt) {
if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop)
@@ -2905,12 +2874,10 @@ void MyMesh::handleCmdFrame(size_t len) {
if (len < 1 + PUB_KEY_SIZE) {
// export SELF
mesh::Packet* pkt;
- char adv_buf[sizeof(((ContactInfo*)0)->name)];
- const char* adv_name = getAdvertNodeName(adv_buf, sizeof(adv_buf));
if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
- pkt = createSelfAdvert(adv_name);
+ pkt = createSelfAdvert(_prefs.node_name);
} else {
- pkt = createSelfAdvert(adv_name, sensors.node_lat, sensors.node_lon);
+ pkt = createSelfAdvert(_prefs.node_name, sensors.node_lat, sensors.node_lon);
}
if (pkt) {
pkt->header |= ROUTE_TYPE_FLOOD; // would normally be sent in this mode
@@ -3791,12 +3758,10 @@ void MyMesh::loop() {
bool MyMesh::advert() {
mesh::Packet* pkt;
- char adv_buf[sizeof(((ContactInfo*)0)->name)];
- const char* adv_name = getAdvertNodeName(adv_buf, sizeof(adv_buf));
if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
- pkt = createSelfAdvert(adv_name);
+ pkt = createSelfAdvert(_prefs.node_name);
} else {
- pkt = createSelfAdvert(adv_name, sensors.node_lat, sensors.node_lon);
+ pkt = createSelfAdvert(_prefs.node_name, sensors.node_lat, sensors.node_lon);
}
if (pkt) {
sendZeroHop(pkt);
diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h
index 711bb69f..46c3ff3c 100644
--- a/examples/companion_radio/MyMesh.h
+++ b/examples/companion_radio/MyMesh.h
@@ -216,7 +216,6 @@ private:
bool observeKnownBotResponse(const BotMessage &message, bool authoritative_sender);
bool observeBotGroupResponse(const BotMessage &message);
void buildBotCommandContext(BotCommandContext &context, BotCommandId command_id);
- bool autoLearnKnownBotAdvert(const ContactInfo &contact);
bool enqueueBotResponse(const BotMessage &message, const ContactInfo *direct_recipient, uint8_t channel_idx,
const char *text, size_t text_len, BotFingerprint request_fingerprint,
BotFingerprint response_fingerprint);
@@ -248,9 +247,6 @@ private:
bool sendBotSelfAdvert(bool flood);
#endif
- const char* getAdvertNodeName(char* buf, size_t buf_len);
-
-
void checkCLIRescueCmd();
void checkSerialInterface();
bool isValidClientRepeatFreq(uint32_t f) const;

View File

@@ -566,22 +566,6 @@ static void test_ack_response_format() {
assert(strncmp(small, "ack @[bob]", 10) == 0);
}
static void test_bot_advert_marker() {
char out[32];
size_t written = 0;
assert(FirmwareBot::writeBotAdvertName("node", out, sizeof(out), &written) == BOT_WRITE_OK);
assert(strcmp(out, "node" BOT_ADVERT_MARKER) == 0);
assert(written == strlen(out));
assert(FirmwareBot::isBotAdvertName(out, strlen(out)));
assert(!FirmwareBot::isBotAdvertName("node", 4));
assert(!FirmwareBot::isBotAdvertName("node [bot]", 10));
char small[12];
assert(FirmwareBot::writeBotAdvertName("very-long-node-name", small, sizeof(small), &written) == BOT_WRITE_TRUNCATED);
assert(FirmwareBot::isBotAdvertName(small, strlen(small)));
assert(written == sizeof(small) - 1);
}
static BotMessage make_message(const char* channel, const char* text) {
BotMessage message;
memset(&message, 0, sizeof(message));
@@ -1661,7 +1645,6 @@ int main() {
test_response_write();
test_channel_text_and_response_guards();
test_ack_response_format();
test_bot_advert_marker();
test_command_outputs();
test_path_command();
test_trace_result_format();