Add exact Waveshare S3 updater target - #70
Conversation
SteveEisner
left a comment
There was a problem hiding this comment.
Reviewed the corrected S3 artifact, provenance metadata, validation rules, and regression coverage. USB and OTA now install one verified application image, and the contract rejects future drift between the two delivery paths.
| "path": "contracts/update/artifacts/waveshare-s3-v14/ota/firmware.bin", | ||
| "buildOffset": 65536, | ||
| "lengthBytes": 1219728, | ||
| "sha256": "247c26185d61d75e372dc3cf91299f82f2749f85c5a4857ffbc2818a08d94ba2" |
There was a problem hiding this comment.
This corrects the critical S3 artifact mismatch: the OTA file now has the same 1,219,728-byte application payload and SHA-256 as the application embedded at offset 65,536 in the merged USB image. Choosing USB or OTA will therefore install the same firmware build.
| "tubesRelease": "14", | ||
| "wledBaseVersion": "16.0.1", | ||
| "releaseIdentity": "WAVESHARE_S3_TUBES_TARGET", | ||
| "buildCommit": "02abdd5d53aeabbcb8eed1bc36b29a1c340afa44", |
There was a problem hiding this comment.
Recording the full 40-character build commit makes this artifact traceable to one exact source revision instead of an abbreviated prefix. That matters when validating or reproducing firmware months later, when a short identifier could be ambiguous or accepted accidentally.
| && artifactsShareBuild(merged, item)); | ||
| fail(errors, !!ota, `${merged.id} is missing matching OTA application`); | ||
| if (ota) fail(errors, | ||
| application.lengthBytes === ota.lengthBytes && application.sha256 === ota.sha256, |
There was a problem hiding this comment.
This is the durable protection against the original failure: every merged USB image must have a matching OTA artifact for the same target, release, identity, commit, and source state, and their application size and hash must agree. A future build can no longer publish two different firmwares as interchangeable delivery formats.
|
|
||
| // A merged image and its OTA artifact represent one build, so their application | ||
| // bytes must remain identical even when both individual files are internally valid. | ||
| test('merged and OTA artifacts from one build share exact application bytes', () => { |
There was a problem hiding this comment.
This regression test independently proves both failure modes that matter: validation rejects an OTA image whose hash differs from the USB application, and it rejects a USB build with no corresponding OTA artifact. It keeps the cross-artifact guarantee covered even when each individual file is internally valid.
|
We’re parking this multi-target updater-contract experiment. Physical S3 work converged on a much smaller device-only target, which will be proposed separately as one focused commit. This PR is being closed rather than rewritten so its updater/C3/migration review history remains accurate. |
Idea
Add a fail-closed, exact-target updater contract for the Waveshare ESP32-S3-Touch-AMOLED-2.16 device, with byte-pinned USB merged and OTA application artifacts.
Three-commit map
8b015680— updater foundations and bounded admission.02abdd5d— exact Athom C3 target.6a1299e5— exact Waveshare S3 target-only contract, generated projections, migration fixture, PlatformIO environment, tests, and clean artifacts.Scope and independence
This PR is intentionally S3 target-only. Home, Conductor, Surveyor, touch/display product development remains independent and is not coupled or superseded by this updater target contract. No product UI files or
platformio.inichanges are included.Verification
npm ci && npm run build && npm test— pass (31 tests)node tools/update-contract/validate.mjs— passnode tools/update-contract/generate.mjs --check— passpio run -e waveshare_s3_tubes_target— passpio run -e esp32-c3-athom_tubes— passpio run -e esp32_quinled_dig2go_tubes— passgit diff --check— passLimitations
No Easy Flash push/deploy, physical device flash, network, Vercel, or DNS actions were performed.
Follow-up fix
Commit
a17370b8makes the S3 OTA artifact byte-identical to the application embedded in the pinned merged USB image. The contract now requires full commit SHAs, matching compiled release identity, and an exact merged/OTA application pair for each build; the migration fixture, generated projections, and documentation were updated from that single byte source.The PlatformIO configuration test now uses the repository's composed project configuration and skips only when PlatformIO is not installed. Validation passes with PlatformIO present and absent.
Additional verification:
npm test— pass (31 passed, one optional PlatformIO test skipped)esp32dev,esp32_quinled_dig2go_tubes,esp32-c3-athom_tubes, andwaveshare_s3_tubes_targetfirmware builds — passgit diff --check— pass