touch: core-v1.17.1 (beta_60 boot loop + unreachable contacts) + release firmware-data gate

Core (core-v1.17.1, meshcomod 5406093): 1.17 reserved MAX_ANON_CONTACTS slots
at the head of contacts[], which broke two things in beta_60 —

- resetContacts() claimed those slots while the lazily-allocated PSRAM table was
  still NULL, so the new bootstrapRTCfromContacts() NULL-deref'd at boot on any
  device whose contact store loaded nothing: fresh install, erase-flash, or SD
  not mounted yet (#249). Boards with saved contacts booted fine, which is how
  it passed bench testing.
- getContactByIdx() stayed raw while getNumContacts() excludes the reserved
  slots, so every pairing of the two — contact list, action sheets, phone-app
  sync, getContactForSave — read empty slots and could not reach the newest 8
  real contacts. A just-added contact was invisible and its action-sheet
  operations resolved to a blank slot (#252).

Fork side:
- loadContacts() skips blank records, clearing the placeholder contacts beta_60
  wrote into the contacts file (the next save drops them permanently).
- Chat threads follow a peer's rename. The thread is matched by key but its name
  was never updated, while inbound messages are filed by sender name — so the
  first message after a rename created a duplicate thread (#252).
- release.sh derives FIRMWARE_VERSION / build date / core version from the tag
  and the pinned core, keeps the in-tree dev default in step, and ABORTS the
  release if any staged image does not embed its own tag. beta_60 shipped
  reporting v1.16.0-touch because that value was hand-maintained.

All 8 S3 envs build green on core-v1.17.1.

Reported-by: Pierre747, rustinmyeye, myshoeisonfire

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kaj SchittecatandClaude Opus 5 committed 2026-08-10 08:20:00 +02:00
1 parent 8cd14d2aea
commit 335a64c118
5 files changed
+62 -8

No files matched your search

+7
View File
@@ -1,6 +1,7 @@
#include <Arduino.h>
#include <string.h>
#include "DataStore.h"
#include <helpers/AdvertDataHelpers.h> // ADV_TYPE_NONE (blank-record skip in loadContacts)
#if defined(ESP32)
#include <SD.h>
#include "helpers/esp32/WdtHeavyGuard.h" // suspend core-0 idle WDT during the (SPIFFS-GC-prone) contact write
@@ -482,6 +483,12 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3");
if (!success) break; // EOF
// Skip blank records. beta_60 saved the core's reserved anon slots (the
// save walked the raw table, which 1.17 had shifted), so an upgrade from
// it carries up to MAX_ANON_CONTACTS empty entries that would otherwise
// load as real, nameless contacts. The next save drops them for good.
if (c.type == ADV_TYPE_NONE || !c.name[0]) continue;
c.id = mesh::Identity(pub_key);
if (!host->onContactLoaded(c)) full = true;
}