Bugs I hit, how I found them, and what fixed them.
The SD card and the RFID reader shared one SPI bus, and the SD card's chip-select line left MISO asserted. Here's how I tracked it down.
Back-to-back blocking buzzer and LED patterns starved the ESP32's task watchdog. A few yield() calls fixed it.
Google Apps Script responses arrived chunked, and the chunk-size markers leaked into the JSON the ESP32 was parsing.