Add peer updater foundations - #67
Conversation
|
Bounded correction receipt ( |
|
Bounded recursive-review receipt ( |
|
Foundation closure is independently green and remains within the draft PR boundary: exact target/artifact contracts, deterministic JS/C++ projections, bounded image/HTTP response sources, one-sender/one-target/one-artifact lease and health state foundations, migration evidence, and forwarding disabled. No live endpoint, receiver write path, or packet/action ID is present. The next implementation slice is blocked on canonical direction rather than branch code: what additive identity/capability report should authorize a peer update? The receiver admission contract needs exact target-versus-relay identity, flash mode/size, partition and inactive-OTA geometry, release/build identity, artifact length/hash, and capability evidence. The current 32-bit release hash is compatibility evidence but not sufficient artifact identity. Could you confirm whether this foundation-only boundary is acceptable for #67 and point us at the canonical report/transport seam you want the next slice to consume? We will not invent a branch-local packet or action ID. |
|
Superseded by clean draft #69, rebuilt from current Steve main as one normal commit with the complete intended net change plus independent-review attribution/documentation cleanup. This PR is being closed for history; its branch is retained and was not force-pushed or deleted. |
The idea in plain language
This work has three parts.
1. A future way for Tubes to update each other
After the fleet is running the new firmware, one updated Tube can pass an approved update to one compatible Tube nearby. The receiver installs it, restarts, and proves it is healthy before the baton moves on. If nothing suitable appears for 60 seconds, propagation stops.
This PR builds the safe state and identity rules for that future path. It does not invent a packet ID while Steve's new protocol is still being defined.
2. A migration from the old fleet to the new one
The hundreds of existing Tubes do not understand the new targeting or baton rules yet. We will move them onto the bridge release with Easy Flash and the regular laptop-assisted OTA workflow they already support. We are not asking one Dig2Go to serve an arbitrary crowd of legacy devices, and we are not pretending the old broadcast command can target one Tube.
Easy Flash handles the first USB seed. The laptop handles the main legacy migration. The S3 updater is the on-site option for devices missed before a rave.
3. A cautious rollout
We start with Greg's four Tubes, including an interrupted transfer and retry. Then we test a small group before expanding to the larger fleet. A device only counts as updated when it restarts and returns healthy; powered-off, absent, or out-of-range devices remain unknown and can be handled in another pass.
The operator instruction stays simple:
What this PR contains today
This is still a draft foundation, not a live end-to-end peer updater. It contains exact-target and artifact admission, inactive-slot geometry, image-source seams, one-sender/one-target session state, health proof, and the post-migration 60-second baton.
Still intentionally absent:
Update.begin()and write integration;Those boundaries are deliberate. The PR does not change the deployed 84-byte Tubes state frame or assign a competing action or packet ID.
Validation
npm ci && npm run buildnpm test— 16 tests passedtest/tubes_mesh/run.sh— all focused mesh/updater contracts passedtest/tubes_upgrade/run.sh— upgrade/device-report compatibility passedpio run -e esp32_quinled_dig2go_tubes— success; RAM 25.8%, flash 79.7%jq -e . migration-fixtures/manifest.jsongit diff --checkNo physical device was contacted or flashed. No generated web headers are included.
Working-set coordination — 2026-08-14
This draft is one of three independent contribution rails based on Steve's
main:Shared rules:
Current thinking
P2P owns peer update mechanics, not browser installation or S3 UI. Admission must know the exact hardware target, flash/partition/OTA geometry, release/build identity, image length, and hash before erase or
Update.begin(). Start with one sender, one selected target, one image, one bounded lease, and health proof before handoff.Legacy means pre-v14 and does not require distinguishing v12 from v13. Current v14 can use the existing device-report seam where positively observed. Next v15 should provide explicit release/build/capability identity through Steve's canonical new protocol. Unknown identity fails closed.
TODO
Centralized update contract progress — 2026-08-14
Commit
14279a4684dbc3a82a17ca4fb3a3f5773dc5438badds the first bounded shared-contract foundation owned by PR #67.contracts/update/update-contract.json(schema v1). It is not a wire packet.Legacy / Current / Next / Unknownclassification; incomplete or silent identity remainsUnknownand fails closed.Validation:
npm ci && npm run build;npm test(22 passed);test/tubes_mesh/run.sh;test/tubes_upgrade/run.sh; contract validation and reproducibility checks;pio run -e esp32_quinled_dig2go_tubes(RAM 25.8%, flash 79.7%);git diff --check. No device was contacted or flashed.Centralized-contract TODO
Independent-review hardening — 2026-08-14
Follow-up commit
3525f560c894deb0fe3eca2f4389aa9154e43332closes the Important findings from the independent contract review without adding a live updater or changing the Tubes wire protocol.releaseHashremains compatibility evidence only, not full release identity.Validation: contract validator and generator check;
npm ci && npm run build;npm test(26 passed);test/tubes_mesh/run.sh;test/tubes_upgrade/run.sh;pio run -e esp32_quinled_dig2go_tubes(RAM 25.8%, flash 79.7%);git diff --check.S3 hardware acceptance remains unproven and no S3 artifact exists. The PR remains draft; no reviewers or merge were requested.
Inactive-slot destination geometry correction — 2026-08-14
Commit
e5ce2666closes the final independent-review blocker without adding any receiver write path, packet/action, wire-layout, or forwarding behavior.buildOffset; it no longer presents0x10000as a receiver destination.writeOffset: 0and absolute component offsets. Generated JavaScript and C++ documentation make those transport-specific semantics explicit; the minimal firmware artifact projection omits source/build offsets.inactiveOtaSlot. All three values must exactly match the selected canonical slot, and the image length must fit.Validation: contract validator; generator
--check;npm ci && npm run build;npm test(26 passed);test/tubes_mesh/run.sh;test/tubes_upgrade/run.sh;uvx platformio run -e esp32_quinled_dig2go_tubes(RAM 25.8%, flash 79.7%);git diff --check. No adapter branch or physical device was contacted. The PR remains draft.Recursive-review receiver evidence correction — 2026-08-14
Commit
84801e8ecloses the recursive review findings without adding a live updater or changing the Tubes wire protocol.<string.h>include hygiene, AI markers, intent comments, and compatibility documentation were audited. Operational session ownership, lease-scoped HTTP endpoint lifetime, receiver writes, forwarding, and any new wire seam remain intentionally absent pending protocol authorization.Validation: contract validator; generator
--check;npm ci && npm run build;npm test(26 passed);test/tubes_mesh/run.sh;test/tubes_upgrade/run.sh;uvx platformio run -e esp32_quinled_dig2go_tubes(RAM 25.8%, flash 79.7%); completec6522ace...84801e8estyle/security/compatibility review;git diff --check. No adapter branch or physical device was contacted. No reviewers or merge were requested; the PR remains draft.Recursive review and adapter checkpoint — 2026-08-14
Canonical contract foundation is reviewed at
84801e8e.Unknown, and unchanged wire/action layouts are covered.Two-stage propagation checkpoint — 2026-08-16
Commit
be82a978adds the bounded post-migration baton: one sender/target, frozen canonical artifact, 60-second idle window, one retry from byte zero, typed artifact/session-bound health proof before handoff, and an artifact-bound one-shot boot marker. It defines no wire IDs, keeps forwarding transport-owned, and never claims absent fleet devices are current. The Dig2Go-only laptop batch now skips other profiles before upload.Validation:
npm ci(success);npm test(26 passed);node --test tools/update-contract/update-contract.test.mjs(10 passed);./test/tubes_mesh/run.sh(all focused tests passed);./test/tubes_upgrade/batch_upgrade_workflow_test.sh(all scenarios passed);pio run -e esp32_quinled_dig2go_tubes(success, RAM 25.8%, flash 79.7%);git diff --check. No device/network OTA/flash was performed. PR remains draft.Independent-review blocker closure — 2026-08-16
Commit
8e4e035bcloses the three baton review blockers without changing the post-migration/non-wire boundary:Validation: focused
tubes_mesh,tubes_upgrade, batch workflow,npm test(26), update-contract tests (10), Dig2Go PlatformIO build (RAM 25.8%, flash 79.6%), andgit diff --check. No device/network OTA/flash was performed. The PR remains draft.