From 100e101d05484dbaa97b6eada57a5ffbbc17ba46 Mon Sep 17 00:00:00 2001 From: Matt Edholm Date: Wed, 6 May 2026 19:42:44 -0400 Subject: [PATCH] feat(device-api): include SHA-256 of served .bin in X-Image-Sha256 header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets the firmware verify integrity end-to-end and discard a corrupt transfer before painting the panel — pairs with the firmware-side hash check that lands in the same series of changes. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/Controller/DeviceImageController.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Controller/DeviceImageController.php b/src/Controller/DeviceImageController.php index 426a3ad..819b6e5 100644 --- a/src/Controller/DeviceImageController.php +++ b/src/Controller/DeviceImageController.php @@ -158,10 +158,17 @@ class DeviceImageController extends AbstractController 'bytes' => filesize($binPath), ]); + // SHA-256 of the .bin lets the device verify integrity end-to-end: + // anything that gets corrupted between Imagick's render and the + // ESP32 framebuffer (TCP edge cases, memory glitch, partial flush) + // is caught before we commit the bytes to NVS or paint the panel. + // The ESP32-S3 has hardware SHA so the verification is essentially + // free on the device side. $response = new BinaryFileResponse($binPath); - $response->headers->set('Content-Type', 'application/octet-stream'); - $response->headers->set('X-Image-Id', (string) $image->getId()); - $response->headers->set('X-Interval-Ms', (string) $intervalMs); + $response->headers->set('Content-Type', 'application/octet-stream'); + $response->headers->set('X-Image-Id', (string) $image->getId()); + $response->headers->set('X-Image-Sha256', hash_file('sha256', $binPath)); + $response->headers->set('X-Interval-Ms', (string) $intervalMs); return $response; }