Skip to content

Add participant-safe Easy Flash recovery - #65

Closed
theysayheygreg wants to merge 9 commits into
SteveEisner:mainfrom
theysayheygreg:contrib/easy-flash
Closed

Add participant-safe Easy Flash recovery#65
theysayheygreg wants to merge 9 commits into
SteveEisner:mainfrom
theysayheygreg:contrib/easy-flash

Conversation

@theysayheygreg

@theysayheygreg theysayheygreg commented Aug 15, 2026

Copy link
Copy Markdown

Summary

Adds a participant-facing, laptop-local Easy Flash installation and recovery surface for the canonical QuinLED Dig2Go Tubes v14 hardware target.

The contribution includes a single-target artifact manifest, integrity-checked USB and OTA downloads, a single Connect → target-bound confirmation → Install flow, Web Serial recovery support, focused tests, and vendored esptool-js licensing/source attribution.

Safety and scope

  • Contains only the canonical Dig2Go hardware artifact; no Pattern, Hello, Purple, spatial, Mobile Conductor, P2P, or Waveshare S3 experiments.
  • Loading the page and preparing a receipt never writes hardware.
  • Direct USB recovery requires explicit browser port selection and confirmation.
  • The ESP ROM proves MCU family, not the controller board. The UI and docs explicitly require physical confirmation that the connected ESP32 is a Dig2Go.
  • The checked-in v14 artifacts are integrity-pinned but have not been hardware-tested in this contribution.

Validation

  • npm ci && npm run build
  • npm test — 33 tests passed
  • npm run test:easy-flash — 17 tests passed
  • git diff --check

No physical device was contacted or flashed. No generated wled00/html_*.h or wled00/js_*.h files are included.


Working-set coordination — 2026-08-14

This draft is one of three independent contribution rails based on Steve's main:

Shared rules:

  • Steve's packet, hardware-identity, and release-metadata contracts remain canonical.
  • Keep the deployed 84-byte Tubes v2 State frame unchanged during migration.
  • Distinguish Tubes protocol version, Tubes release, WLED base version, hardware target, and runtime profile.
  • Use broad firmware classes: Legacy (pre-v14), Current (v14/WLED 16), Next (v15/new protocol), and Unknown. Missing evidence remains Unknown.
  • v15 should advertise release/build identity and capabilities through Steve's additive versioned protocol—not a branch-local packet ID.
  • Firmware variants represent hardware/compiled boundaries only. Art, role, palette, tempo, pattern, spatial policy, and installation identity remain runtime configuration.
  • Any shared contract change is checked against all three drafts before one advances.

Current thinking

Easy Flash is the wired installation/recovery authority. It selects a hardware-compatible artifact, backs up effective state, installs the exact image, proves the destination boot, then applies only a compatible runtime profile. It does not own peer transport or S3 interaction design.

TODO

  • Confirm whether explicit physical Dig2Go confirmation is acceptable until a canonical exact-board identity seam exists.
  • Replace installer-local identity assumptions with Steve's canonical hardware target and release manifest when defined.
  • Keep release number and build hash separate in artifacts and receipts.
  • Prove configuration backup and post-flash read-back on authorized hardware.
  • Add v15 only after its exact hardware, release, and capability metadata are canonical.
  • Keep runtime profiles separate from firmware artifacts and apply them only after destination health proof.

Desktop application progress — 2026-08-14

Commits 02858748 and 9810e50e adds an Electron wrapper around the existing participant-safe browser flow. It launches directly into the bundled Easy Flash UI through a secure local protocol, keeps Web Serial and esptool-js local, requires explicit serial-port selection plus physical Dig2Go confirmation, and does not select or flash a device on launch. Production windows are sandboxed, have no renderer Node access or DevTools, deny external navigation/windows, and block HTTP/HTTPS/file requests.

Packaging now produces unsigned macOS arm64 .app, DMG, and ZIP artifacts locally, and configures unsigned Windows x64 NSIS/ZIP artifacts on windows-2022 CI. Firmware bytes and manifest SHA-256 values are unchanged. The packaged no-device smoke proves a secure wledtubes: renderer, Web Serial availability, and bundled manifest loading. No hardware was contacted or flashed.

The participant docs now describe Download → Open → Connect → Confirm → Backup/Review → Install, with an explicit caveat that this draft saves planning/firmware receipts but does not yet perform a complete on-device configuration backup. Gatekeeper/SmartScreen behavior and future signing/notarization requirements are documented. Third-party runtime and esptool-js notices are included.

Desktop TODO

  • Package the canonical Easy Flash UI as a local macOS application with DMG/ZIP outputs.
  • Configure Windows x64 NSIS/ZIP packaging and a macOS/Windows artifact workflow.
  • Preserve explicit port selection, physical Dig2Go confirmation, hash checks, and final write approval.
  • Keep preparation/read-only receipt paths side-effect free and preserve browser/Web Serial usage.
  • Ship Electron/Chromium, WLED, esptool-js, and bundled dependency notices.
  • Complete Windows x64 CI packaging proof for this commit.
  • Add Apple Developer ID signing, hardened runtime, and notarization.
  • Add Windows Authenticode signing and publisher reputation.
  • Implement and validate a complete read-only device configuration backup on authorized hardware.
  • Prove post-flash read-back and destination boot on authorized Dig2Go hardware.
  • Publish release artifact SHA-256 values alongside participant downloads.
  • Replace the default Electron app icon with approved WLEDTubes artwork.

Buy. Build. Rave. onboarding — 2026-08-14

The Easy Flash portal and top-level DIY README now open with Buy. Build. Rave.

  • Buy: QuinLED Dig2Go is the exact supported controller. The complete strip/power/connector/tube shopping kit remains provisional and is not presented as certified.
  • Build: assemble the Tube and let Easy Flash handle verified firmware and setup without developer tools.
  • Rave: power it safely and bring it near the flock.

The README retains Steve's detailed project and developer reference below the concise opener. A focused UI contract test protects the headline. The server test suite now uses one awaited lifecycle and exits cleanly instead of leaving a listener alive.

Onboarding TODO

  • Pin and validate one exact full physical kit: strip, power source, connectors, tube/diffuser, and mechanical parts.
  • Add official signed Mac and Windows release links when signing and hardware acceptance are complete.
  • Replace provisional strip/power planner defaults with validated kit values.

Central update-contract integration checkpoint — 2026-08-14

This source PR remains independently based on Steve main. A disposable integration worktree proved Easy Flash consumption of PR #67's generated contract without changing this branch. Reviewed adapter commits: 1133cf28 and 41b0a03e.

  • Canonical target/artifact identity replaces the independent installer manifest.
  • Generic ESP32 identity alone cannot admit a write; current Dig2Go recovery requires explicit target-bound physical confirmation and records that evidence as a fallback, not machine proof.
  • Merged-image component geometry and hashes are revalidated immediately before write.
  • Receipts stop at AwaitingHealth; backup, read-back, mesh rejoin, and health remain unproven.
  • Reconstruct these adapter commits only after the canonical contract is accepted; do not permanently stack the open PRs.

Integrity hardening — 2026-08-15

Commit 9fc89667 fixes confirmed artifact-resolution integrity bugs without changing browser/Electron routes, filenames, firmware bytes, or manifest SHA-256 values.

  • Manifest loading now rejects duplicate variant IDs, duplicate present artifact IDs, and duplicate transports per variant.
  • Artifact roots must exist as real directories and may not be symlinks. Root and candidate paths are canonicalized with realpath and checked with separator-safe containment, covering direct ../, sibling-prefix, cross-drive, and symlink escapes.
  • The resolver opens an artifact once, performs fstat, read, size, and SHA-256 validation on that handle, then returns the verified byte snapshot. The HTTP server and Electron protocol consume those bytes directly instead of reopening a verified path.
  • Deterministic regressions cover all collision classes, traversal, artifacts-evil, symlink escape, missing/symlinked roots, and path.win32 separator/drive behavior. HTTP response bytes are hashed against the unchanged manifest hash.

Validation: npm run test:easy-flash 26/26; npm test 42/42; unsigned macOS arm64 app/DMG/ZIP package succeeded; ASAR allowlist inspection found the resolver, desktop handler, manifest, and both firmware binaries; packaged no-device smoke passed; git diff --check passed.

Equivalent focused reconstruction was proven locally atop canonical adapter 41b0a03e as local-only commit 532d519a (not pushed): canonical validation/generation clean, Easy Flash 37/37, repository 63/63, package/ASAR smoke passed. No device, signing, reviewer, merge, or draft-state change.

Forge artifact-root race correction (2026-08-15)

Removed the residual root lstatrealpath policy race. The resolver now compares the root canonical identity with its lexical location using native platform normalization, opens and retains the candidate once, then revalidates root identity while that handle is open. Deterministic hooks prove initial symlink/canonical mismatch and replacement on repeated canonicalization; POSIX/macOS and Windows path rules remain covered.

Residual boundary: Node/Electron ASAR and Windows do not share a portable no-follow directory-handle contract, so replace-and-restore wholly between checks or replacement after the final check remains possible. It cannot alter the immutable bytes returned from the single open handle after exact size and pinned SHA-256 verification.

Receipt: source commit 9700cfa0; npm run test:easy-flash 28/28; npm test 44/44; git diff --check clean. Mirrored canonical integration commit 7a55bdf7 is local-only and was not pushed. Integration passed 39/39 focused, 65/65 full, 10/10 contract checks, deterministic generation, unsigned mac arm64 DMG/ZIP packaging, ASAR allowlist inspection, and packaged smoke. No device, signing, reviewer, or merge action.


Easy Flash one-action simplification — 2026-08-15

Commit 43565ffe replaces the planner/test-bench split with the participant flow Greg requested: Plug in controller → Connect → Install. Connect opens the browser-required serial chooser once, inspects the ESP ROM, and retains that exact session. The sole Dig2Go USB recovery artifact is selected internally; Install remains a separate explicit action and never starts on connect. Firmware cards, downloads, test buttons, technical acceptance fields, manual variants, and scroll-dependent controls are absent from the primary screen. Advanced evidence remains collapsed.

The evidence audit found no stable Dig2Go-specific VID/PID, USB serial marker, ROM signature, or trusted MAC inventory in the repository. VID/PID and ROM chip family therefore remain chip/transport observations, not board proof. After a matching ESP32 is detected, the UI asks for one concise printed-label confirmation: Yes, this is a QuinLED Dig2Go. A fixture-tested running-device adapter can positively match exact Tubes/Dig2Go release plus hardware family/variant identity and rejects generic WLED, MAC, ESP32, or pin resemblance.

The write path checks the exact image, preserves settings with eraseAll: false, resets, and waits. It truthfully reports backup unavailable, writer-return/readback evidence, and health unverified; it never claims Complete without boot proof. No device was contacted.

Validation: Easy Flash 25/25; full repository 41/41; unsigned macOS arm64 DMG/ZIP package and packaged smoke passed; ASAR allowlist clean; git diff --check clean. Windows x64 packaging remains covered by the existing windows-2022 workflow contract. A canonical-contract reconstruction preserving base 7a55bdf7 is local-only at daa248eb; canonical validation/generation, Easy Flash 33/33, full repository 59/59, package, ASAR, and smoke passed. No signing, merge, reviewer request, or ready-for-review transition.


Independent-review safety correction — 2026-08-15

Commit aff451d9 corrects the simplified Easy Flash blockers without restoring planner, firmware-picker, or test-bench UI.

  • The executed UI→install seam now passes exact target-bound physicalConfirmation (asserted, targetId, printedModel). Unchecked confirmation blocks; matching confirmation reaches a mocked pre-write boundary; wrong target/model blocks.
  • The source branch temporarily derives fail-closed component validation from its existing manifest: exact required component IDs, safe integer and image/flash bounds, overlap rejection, whole-image SHA-256, and every component-slice SHA-256. safety-contract.mjs and operation-receipts.mjs are isolated adapters intended for direct replacement by PR Add peer updater foundations #67 canonical modules.
  • Receipts distinguish validation, transport, pre-write identity, write, reset, failure, and awaiting-health stages without claiming backup, readback, boot health, or mesh rejoin.
  • Prepared installs require an immutable session token and exact SerialPort, freeze chip/USB observations, and immediately recheck port observations plus ESP chip family before write. Stale, replayed, swapped, or disconnected sessions fail closed.
  • Web Serial disconnect closes transport, invalidates only the matching session, clears confirmation, hides/disables Install, focuses Connect, and announces plain reconnect guidance. Detection focuses the next required control and announces it through the live region.
  • The server suite now owns a fresh server instance and closes active/idle connections deterministically; the prior teardown hang is not waived.

Source proof: Easy Flash 30/30; full repository 46/46; Windows path checks 2/2; git diff --check; unsigned macOS arm64 DMG/ZIP and ASAR allowlist smoke. Package SHA-256: DMG 06bf64016679b5971a795647f860397a1f366a22006d0ad9ba4ac14ff85e887f; ZIP 8e868fc9c422567782f5154cb4424d98728a3c00b799b7c761da39fb267bbc55.

Canonical integration remains local-only on base daa248eb: Easy Flash 37/37; full repository 63/63; focused contract 27/27; canonical validator clean; unsigned macOS package and ASAR allowlist smoke. Package SHA-256: DMG 5740377baa5781972920cbf0f775f051a47e2c3cb566af67fe477cc846654d85; ZIP 91d7deccfe9952fb7864b39e6ae4f525e582d57604fee175796edf1c025161cf.

No device was contacted or flashed. No signing, merge, reviewer request, or ready-for-review action was performed.

@theysayheygreg

Copy link
Copy Markdown
Author

Closing because Easy Flash is now maintained and handed off as its own standalone static application: https://github.com/theysayheygreg/WLEDTubes-Easy-Flash. The standalone repository pins canonical WLEDTubes source, builds the approved Dig2Go firmware in GitHub Actions, verifies immutable release provenance, and carries the current participant-facing UI and Vercel handoff. Keeping this older in-tree implementation open would create two apparent Easy Flash authorities.

@theysayheygreg
theysayheygreg deleted the contrib/easy-flash branch August 26, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant